import org.eclipse.jgit.diff.EditList;
import org.eclipse.jgit.diff.MyersDiff;
import org.eclipse.jgit.diff.RawText;
+import org.eclipse.jgit.diff.RawTextComparator;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.iplog.Committer.ActiveRange;
import org.eclipse.jgit.lib.BlobBasedConfig;
else
oldImage = new byte[0];
- EditList edits = new MyersDiff(new RawText(oldImage),
+ EditList edits = new MyersDiff<RawText>(
+ RawTextComparator.DEFAULT, new RawText(oldImage),
new RawText(openBlob(1))).getEdits();
for (Edit e : edits)
addedLines += e.getEndB() - e.getBeginB();
import org.eclipse.jgit.diff.DiffEntry;
import org.eclipse.jgit.diff.DiffFormatter;
-import org.eclipse.jgit.diff.RawTextIgnoreAllWhitespace;
-import org.eclipse.jgit.diff.RawTextIgnoreLeadingWhitespace;
-import org.eclipse.jgit.diff.RawTextIgnoreTrailingWhitespace;
-import org.eclipse.jgit.diff.RawTextIgnoreWhitespaceChange;
+import org.eclipse.jgit.diff.RawTextComparator;
import org.eclipse.jgit.diff.RenameDetector;
import org.eclipse.jgit.dircache.DirCacheIterator;
import org.eclipse.jgit.lib.ObjectId;
@Option(name = "--ignore-space-at-eol")
void ignoreSpaceAtEol(@SuppressWarnings("unused") boolean on) {
- diffFmt.setRawTextFactory(RawTextIgnoreTrailingWhitespace.FACTORY);
+ diffFmt.setDiffComparator(RawTextComparator.WS_IGNORE_TRAILING);
}
@Option(name = "--ignore-leading-space")
void ignoreLeadingSpace(@SuppressWarnings("unused") boolean on) {
- diffFmt.setRawTextFactory(RawTextIgnoreLeadingWhitespace.FACTORY);
+ diffFmt.setDiffComparator(RawTextComparator.WS_IGNORE_LEADING);
}
@Option(name = "-b", aliases = { "--ignore-space-change" })
void ignoreSpaceChange(@SuppressWarnings("unused") boolean on) {
- diffFmt.setRawTextFactory(RawTextIgnoreWhitespaceChange.FACTORY);
+ diffFmt.setDiffComparator(RawTextComparator.WS_IGNORE_CHANGE);
}
@Option(name = "-w", aliases = { "--ignore-all-space" })
void ignoreAllSpace(@SuppressWarnings("unused") boolean on) {
- diffFmt.setRawTextFactory(RawTextIgnoreAllWhitespace.FACTORY);
+ diffFmt.setDiffComparator(RawTextComparator.WS_IGNORE_ALL);
}
@Option(name = "-U", aliases = { "--unified" }, metaVar = "metaVar_linesOfContext")
import java.util.TimeZone;
import org.eclipse.jgit.diff.DiffFormatter;
-import org.eclipse.jgit.diff.RawTextIgnoreAllWhitespace;
-import org.eclipse.jgit.diff.RawTextIgnoreLeadingWhitespace;
-import org.eclipse.jgit.diff.RawTextIgnoreTrailingWhitespace;
-import org.eclipse.jgit.diff.RawTextIgnoreWhitespaceChange;
+import org.eclipse.jgit.diff.RawTextComparator;
import org.eclipse.jgit.diff.RenameDetector;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.Constants;
@Option(name = "--ignore-space-at-eol")
void ignoreSpaceAtEol(@SuppressWarnings("unused") boolean on) {
- diffFmt.setRawTextFactory(RawTextIgnoreTrailingWhitespace.FACTORY);
+ diffFmt.setDiffComparator(RawTextComparator.WS_IGNORE_TRAILING);
}
@Option(name = "--ignore-leading-space")
void ignoreLeadingSpace(@SuppressWarnings("unused") boolean on) {
- diffFmt.setRawTextFactory(RawTextIgnoreLeadingWhitespace.FACTORY);
+ diffFmt.setDiffComparator(RawTextComparator.WS_IGNORE_LEADING);
}
@Option(name = "-b", aliases = { "--ignore-space-change" })
void ignoreSpaceChange(@SuppressWarnings("unused") boolean on) {
- diffFmt.setRawTextFactory(RawTextIgnoreWhitespaceChange.FACTORY);
+ diffFmt.setDiffComparator(RawTextComparator.WS_IGNORE_CHANGE);
}
@Option(name = "-w", aliases = { "--ignore-all-space" })
void ignoreAllSpace(@SuppressWarnings("unused") boolean on) {
- diffFmt.setRawTextFactory(RawTextIgnoreAllWhitespace.FACTORY);
+ diffFmt.setDiffComparator(RawTextComparator.WS_IGNORE_ALL);
}
@Option(name = "-U", aliases = { "--unified" }, metaVar = "metaVar_linesOfContext")
String b = DiffTestDataGenerator.generateSequence(characters, 1621, 5);
CharArray ac = new CharArray(a);
CharArray bc = new CharArray(b);
- MyersDiff myersDiff = null;
+ CharCmp cmp = new CharCmp();
+ MyersDiff<CharArray> myersDiff = null;
int cpuTimeChanges = 0;
long lastReadout = 0;
long interimTime = 0;
int repetitions = 0;
stopwatch.start();
while (cpuTimeChanges < minCPUTimerTicks && interimTime < longTaskBoundary) {
- myersDiff = new MyersDiff(ac, bc);
+ myersDiff = new MyersDiff<CharArray>(cmp, ac, bc);
repetitions++;
interimTime = stopwatch.readout();
if (interimTime != lastReadout) {
}
}
ret.runningTime = stopwatch.stop() / repetitions;
- ret.N = (ac.size() + bc.size());
+ ret.N = ac.size() + bc.size();
ret.D = myersDiff.getEdits().size();
return ret;
}
- private static class CharArray implements Sequence {
- private final char[] array;
+ private static class CharArray extends Sequence {
+ final char[] array;
public CharArray(String s) {
array = s.toCharArray();
}
+ @Override
public int size() {
return array.length;
}
+ }
+
+ private static class CharCmp extends SequenceComparator<CharArray> {
+ @Override
+ public boolean equals(CharArray a, int ai, CharArray b, int bi) {
+ return a.array[ai] == b.array[bi];
+ }
- public boolean equals(int i, Sequence other, int j) {
- CharArray o = (CharArray) other;
- return array[i] == o.array[j];
+ @Override
+ public int hash(CharArray seq, int ptr) {
+ return seq.array[ptr];
}
}
}
}
public void assertDiff(String a, String b, String edits) {
- MyersDiff diff = new MyersDiff(toCharArray(a), toCharArray(b));
+ MyersDiff diff = new MyersDiff<CharArray>(new CharCmp(),
+ toCharArray(a), toCharArray(b));
assertEquals(edits, toString(diff.getEdits()));
}
return new CharArray(s);
}
- protected static String toString(Sequence seq, int begin, int end) {
- CharArray a = (CharArray)seq;
+ protected static String toString(CharArray a, int begin, int end) {
return new String(a.array, begin, end - begin);
}
+ ")";
}
- private static class CharArray implements Sequence {
+ private static class CharArray extends Sequence {
char[] array;
public CharArray(String s) { array = s.toCharArray(); }
public int size() { return array.length; }
- public boolean equals(int i, Sequence other, int j) {
- CharArray o = (CharArray)other;
- return array[i] == o.array[j];
+ }
+
+ private static class CharCmp extends SequenceComparator<CharArray> {
+ @Override
+ public boolean equals(CharArray a, int ai, CharArray b, int bi) {
+ return a.array[ai] == b.array[bi];
+ }
+
+ @Override
+ public int hash(CharArray seq, int ptr) {
+ return seq.array[ptr];
}
}
}
import junit.framework.TestCase;
public class RawTextIgnoreAllWhitespaceTest extends TestCase {
+ private final RawTextComparator cmp = RawTextComparator.WS_IGNORE_ALL;
+
public void testEqualsWithoutWhitespace() {
- final RawText a = new RawTextIgnoreAllWhitespace(Constants
+ final RawText a = new RawText(cmp, Constants
.encodeASCII("foo-a\nfoo-b\nfoo\n"));
- final RawText b = new RawTextIgnoreAllWhitespace(Constants
+ final RawText b = new RawText(cmp, Constants
.encodeASCII("foo-b\nfoo-c\nf\n"));
assertEquals(3, a.size());
assertEquals(3, b.size());
// foo-a != foo-b
- assertFalse(a.equals(0, b, 0));
- assertFalse(b.equals(0, a, 0));
+ assertFalse(cmp.equals(a, 0, b, 0));
+ assertFalse(cmp.equals(b, 0, a, 0));
// foo-b == foo-b
- assertTrue(a.equals(1, b, 0));
- assertTrue(b.equals(0, a, 1));
+ assertTrue(cmp.equals(a, 1, b, 0));
+ assertTrue(cmp.equals(b, 0, a, 1));
// foo != f
- assertFalse(a.equals(2, b, 2));
- assertFalse(b.equals(2, a, 2));
+ assertFalse(cmp.equals(a, 2, b, 2));
+ assertFalse(cmp.equals(b, 2, a, 2));
}
public void testEqualsWithWhitespace() {
- final RawText a = new RawTextIgnoreAllWhitespace(Constants
+ final RawText a = new RawText(cmp, Constants
.encodeASCII("foo-a\n \n a b c\na \n"));
- final RawText b = new RawTextIgnoreAllWhitespace(Constants
+ final RawText b = new RawText(cmp, Constants
.encodeASCII("foo-a b\n\nab c\na\n"));
// "foo-a" != "foo-a b"
- assertFalse(a.equals(0, b, 0));
- assertFalse(b.equals(0, a, 0));
+ assertFalse(cmp.equals(a, 0, b, 0));
+ assertFalse(cmp.equals(b, 0, a, 0));
// " " == ""
- assertTrue(a.equals(1, b, 1));
- assertTrue(b.equals(1, a, 1));
+ assertTrue(cmp.equals(a, 1, b, 1));
+ assertTrue(cmp.equals(b, 1, a, 1));
// " a b c" == "ab c"
- assertTrue(a.equals(2, b, 2));
- assertTrue(b.equals(2, a, 2));
+ assertTrue(cmp.equals(a, 2, b, 2));
+ assertTrue(cmp.equals(b, 2, a, 2));
// "a " == "a"
- assertTrue(a.equals(3, b, 3));
- assertTrue(b.equals(3, a, 3));
+ assertTrue(cmp.equals(a, 3, b, 3));
+ assertTrue(cmp.equals(b, 3, a, 3));
}
}
import junit.framework.TestCase;
public class RawTextIgnoreLeadingWhitespaceTest extends TestCase {
+ private final RawTextComparator cmp = RawTextComparator.WS_IGNORE_LEADING;
+
public void testEqualsWithoutWhitespace() {
- final RawText a = new RawTextIgnoreLeadingWhitespace(Constants
+ final RawText a = new RawText(cmp, Constants
.encodeASCII("foo-a\nfoo-b\nfoo\n"));
- final RawText b = new RawTextIgnoreLeadingWhitespace(Constants
+ final RawText b = new RawText(cmp, Constants
.encodeASCII("foo-b\nfoo-c\nf\n"));
assertEquals(3, a.size());
assertEquals(3, b.size());
// foo-a != foo-b
- assertFalse(a.equals(0, b, 0));
- assertFalse(b.equals(0, a, 0));
+ assertFalse(cmp.equals(a, 0, b, 0));
+ assertFalse(cmp.equals(b, 0, a, 0));
// foo-b == foo-b
- assertTrue(a.equals(1, b, 0));
- assertTrue(b.equals(0, a, 1));
+ assertTrue(cmp.equals(a, 1, b, 0));
+ assertTrue(cmp.equals(b, 0, a, 1));
// foo != f
- assertFalse(a.equals(2, b, 2));
- assertFalse(b.equals(2, a, 2));
+ assertFalse(cmp.equals(a, 2, b, 2));
+ assertFalse(cmp.equals(b, 2, a, 2));
}
public void testEqualsWithWhitespace() {
- final RawText a = new RawTextIgnoreLeadingWhitespace(Constants
+ final RawText a = new RawText(cmp, Constants
.encodeASCII("foo-a\n \n a b c\n a\nb \n"));
- final RawText b = new RawTextIgnoreLeadingWhitespace(Constants
+ final RawText b = new RawText(cmp, Constants
.encodeASCII("foo-a b\n\nab c\na\nb\n"));
// "foo-a" != "foo-a b"
- assertFalse(a.equals(0, b, 0));
- assertFalse(b.equals(0, a, 0));
+ assertFalse(cmp.equals(a, 0, b, 0));
+ assertFalse(cmp.equals(b, 0, a, 0));
// " " == ""
- assertTrue(a.equals(1, b, 1));
- assertTrue(b.equals(1, a, 1));
+ assertTrue(cmp.equals(a, 1, b, 1));
+ assertTrue(cmp.equals(b, 1, a, 1));
// " a b c" != "ab c"
- assertFalse(a.equals(2, b, 2));
- assertFalse(b.equals(2, a, 2));
+ assertFalse(cmp.equals(a, 2, b, 2));
+ assertFalse(cmp.equals(b, 2, a, 2));
// " a" == "a"
- assertTrue(a.equals(3, b, 3));
- assertTrue(b.equals(3, a, 3));
+ assertTrue(cmp.equals(a, 3, b, 3));
+ assertTrue(cmp.equals(b, 3, a, 3));
// "b " != "b"
- assertFalse(a.equals(4, b, 4));
- assertFalse(b.equals(4, a, 4));
+ assertFalse(cmp.equals(a, 4, b, 4));
+ assertFalse(cmp.equals(b, 4, a, 4));
}
}
import junit.framework.TestCase;
public class RawTextIgnoreTrailingWhitespaceTest extends TestCase {
+ private final RawTextComparator cmp = RawTextComparator.WS_IGNORE_TRAILING;
+
public void testEqualsWithoutWhitespace() {
- final RawText a = new RawTextIgnoreTrailingWhitespace(Constants
+ final RawText a = new RawText(cmp, Constants
.encodeASCII("foo-a\nfoo-b\nfoo\n"));
- final RawText b = new RawTextIgnoreTrailingWhitespace(Constants
+ final RawText b = new RawText(cmp, Constants
.encodeASCII("foo-b\nfoo-c\nf\n"));
assertEquals(3, a.size());
assertEquals(3, b.size());
// foo-a != foo-b
- assertFalse(a.equals(0, b, 0));
- assertFalse(b.equals(0, a, 0));
+ assertFalse(cmp.equals(a, 0, b, 0));
+ assertFalse(cmp.equals(b, 0, a, 0));
// foo-b == foo-b
- assertTrue(a.equals(1, b, 0));
- assertTrue(b.equals(0, a, 1));
+ assertTrue(cmp.equals(a, 1, b, 0));
+ assertTrue(cmp.equals(b, 0, a, 1));
// foo != f
- assertFalse(a.equals(2, b, 2));
- assertFalse(b.equals(2, a, 2));
+ assertFalse(cmp.equals(a, 2, b, 2));
+ assertFalse(cmp.equals(b, 2, a, 2));
}
public void testEqualsWithWhitespace() {
- final RawText a = new RawTextIgnoreTrailingWhitespace(Constants
+ final RawText a = new RawText(cmp, Constants
.encodeASCII("foo-a\n \n a b c\na \n b\n"));
- final RawText b = new RawTextIgnoreTrailingWhitespace(Constants
+ final RawText b = new RawText(cmp, Constants
.encodeASCII("foo-a b\n\nab c\na\nb\n"));
// "foo-a" != "foo-a b"
- assertFalse(a.equals(0, b, 0));
- assertFalse(b.equals(0, a, 0));
+ assertFalse(cmp.equals(a, 0, b, 0));
+ assertFalse(cmp.equals(b, 0, a, 0));
// " " == ""
- assertTrue(a.equals(1, b, 1));
- assertTrue(b.equals(1, a, 1));
+ assertTrue(cmp.equals(a, 1, b, 1));
+ assertTrue(cmp.equals(b, 1, a, 1));
// " a b c" != "ab c"
- assertFalse(a.equals(2, b, 2));
- assertFalse(b.equals(2, a, 2));
+ assertFalse(cmp.equals(a, 2, b, 2));
+ assertFalse(cmp.equals(b, 2, a, 2));
// "a " == "a"
- assertTrue(a.equals(3, b, 3));
- assertTrue(b.equals(3, a, 3));
+ assertTrue(cmp.equals(a, 3, b, 3));
+ assertTrue(cmp.equals(b, 3, a, 3));
// " b" != "b"
- assertFalse(a.equals(4, b, 4));
- assertFalse(b.equals(4, a, 4));
+ assertFalse(cmp.equals(a, 4, b, 4));
+ assertFalse(cmp.equals(b, 4, a, 4));
}
}
import junit.framework.TestCase;
public class RawTextIgnoreWhitespaceChangeTest extends TestCase {
+ private final RawTextComparator cmp = RawTextComparator.WS_IGNORE_CHANGE;
+
public void testEqualsWithoutWhitespace() {
- final RawText a = new RawTextIgnoreWhitespaceChange(Constants
+ final RawText a = new RawText(cmp, Constants
.encodeASCII("foo-a\nfoo-b\nfoo\n"));
- final RawText b = new RawTextIgnoreWhitespaceChange(Constants
+ final RawText b = new RawText(cmp, Constants
.encodeASCII("foo-b\nfoo-c\nf\n"));
assertEquals(3, a.size());
assertEquals(3, b.size());
// foo-a != foo-b
- assertFalse(a.equals(0, b, 0));
- assertFalse(b.equals(0, a, 0));
+ assertFalse(cmp.equals(a, 0, b, 0));
+ assertFalse(cmp.equals(b, 0, a, 0));
// foo-b == foo-b
- assertTrue(a.equals(1, b, 0));
- assertTrue(b.equals(0, a, 1));
+ assertTrue(cmp.equals(a, 1, b, 0));
+ assertTrue(cmp.equals(b, 0, a, 1));
// foo != f
- assertFalse(a.equals(2, b, 2));
- assertFalse(b.equals(2, a, 2));
+ assertFalse(cmp.equals(a, 2, b, 2));
+ assertFalse(cmp.equals(b, 2, a, 2));
}
public void testEqualsWithWhitespace() {
- final RawText a = new RawTextIgnoreWhitespaceChange(
- Constants
- .encodeASCII("foo-a\n \n a b c\na \n foo\na b c\n"));
- final RawText b = new RawTextIgnoreWhitespaceChange(Constants
+ final RawText a = new RawText(cmp, Constants
+ .encodeASCII("foo-a\n \n a b c\na \n foo\na b c\n"));
+ final RawText b = new RawText(cmp, Constants
.encodeASCII("foo-a b\n\nab c\na\nfoo\na b c \n"));
// "foo-a" != "foo-a b"
- assertFalse(a.equals(0, b, 0));
- assertFalse(b.equals(0, a, 0));
+ assertFalse(cmp.equals(a, 0, b, 0));
+ assertFalse(cmp.equals(b, 0, a, 0));
// " " == ""
- assertTrue(a.equals(1, b, 1));
- assertTrue(b.equals(1, a, 1));
+ assertTrue(cmp.equals(a, 1, b, 1));
+ assertTrue(cmp.equals(b, 1, a, 1));
// " a b c" != "ab c"
- assertFalse(a.equals(2, b, 2));
- assertFalse(b.equals(2, a, 2));
+ assertFalse(cmp.equals(a, 2, b, 2));
+ assertFalse(cmp.equals(b, 2, a, 2));
// "a " == "a"
- assertTrue(a.equals(3, b, 3));
- assertTrue(b.equals(3, a, 3));
+ assertTrue(cmp.equals(a, 3, b, 3));
+ assertTrue(cmp.equals(b, 3, a, 3));
// " foo" != "foo"
- assertFalse(a.equals(4, b, 4));
- assertFalse(b.equals(4, a, 4));
+ assertFalse(cmp.equals(a, 4, b, 4));
+ assertFalse(cmp.equals(b, 4, a, 4));
// "a b c" == "a b c "
- assertTrue(a.equals(5, b, 5));
- assertTrue(b.equals(5, a, 5));
+ assertTrue(cmp.equals(a, 5, b, 5));
+ assertTrue(cmp.equals(b, 5, a, 5));
}
}
public void testEquals() {
final RawText a = new RawText(Constants.encodeASCII("foo-a\nfoo-b\n"));
final RawText b = new RawText(Constants.encodeASCII("foo-b\nfoo-c\n"));
+ RawTextComparator cmp = RawTextComparator.DEFAULT;
assertEquals(2, a.size());
assertEquals(2, b.size());
// foo-a != foo-b
- assertFalse(a.equals(0, b, 0));
- assertFalse(b.equals(0, a, 0));
+ assertFalse(cmp.equals(a, 0, b, 0));
+ assertFalse(cmp.equals(b, 0, a, 0));
// foo-b == foo-b
- assertTrue(a.equals(1, b, 0));
- assertTrue(b.equals(0, a, 1));
+ assertTrue(cmp.equals(a, 1, b, 0));
+ assertTrue(cmp.equals(b, 0, a, 1));
}
public void testWriteLine1() throws IOException {
import junit.framework.TestCase;
import org.eclipse.jgit.diff.RawText;
+import org.eclipse.jgit.diff.RawTextComparator;
import org.eclipse.jgit.lib.Constants;
public class MergeAlgorithmTest extends TestCase {
}
private String merge(String commonBase, String ours, String theirs) throws IOException {
- MergeResult r=MergeAlgorithm.merge(new RawText(Constants.encode(commonBase)), new RawText(Constants.encode(ours)), new RawText(Constants.encode(theirs)));
+ MergeResult r=MergeAlgorithm.merge(RawTextComparator.DEFAULT, new RawText(Constants.encode(commonBase)), new RawText(Constants.encode(ours)), new RawText(Constants.encode(theirs)));
ByteArrayOutputStream bo=new ByteArrayOutputStream(50);
fmt.formatMerge(bo, r, "B", "O", "T", Constants.CHARACTER_ENCODING);
return new String(bo.toByteArray(), Constants.CHARACTER_ENCODING);
ThreeWayMerger merger = (ThreeWayMerger) mergeStrategy
.newMerger(repo);
boolean noProblems;
- Map<String, org.eclipse.jgit.merge.MergeResult> lowLevelResults = null;
+ Map<String, org.eclipse.jgit.merge.MergeResult<?>> lowLevelResults = null;
Map<String, MergeFailureReason> failingPaths = null;
if (merger instanceof ResolveMerger) {
ResolveMerger resolveMerger = (ResolveMerger) merger;
*/
public MergeResult(ObjectId newHead, ObjectId base,
ObjectId[] mergedCommits, MergeStatus mergeStatus,
- Map<String, org.eclipse.jgit.merge.MergeResult> lowLevelResults,
+ Map<String, org.eclipse.jgit.merge.MergeResult<?>> lowLevelResults,
MergeStrategy mergeStrategy) {
this(newHead, base, mergedCommits, mergeStatus, mergeStrategy, lowLevelResults, null);
}
public MergeResult(ObjectId newHead, ObjectId base,
ObjectId[] mergedCommits, MergeStatus mergeStatus,
MergeStrategy mergeStrategy,
- Map<String, org.eclipse.jgit.merge.MergeResult> lowLevelResults,
+ Map<String, org.eclipse.jgit.merge.MergeResult<?>> lowLevelResults,
String description) {
this.newHead = newHead;
this.mergedCommits = mergedCommits;
* @param path
* @param lowLevelResult
*/
- public void addConflict(String path, org.eclipse.jgit.merge.MergeResult lowLevelResult) {
+ public void addConflict(String path, org.eclipse.jgit.merge.MergeResult<?> lowLevelResult) {
if (conflicts == null)
conflicts = new HashMap<String, int[][]>();
int nrOfConflicts = 0;
import org.eclipse.jgit.lib.ProgressMonitor;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.patch.FileHeader;
-import org.eclipse.jgit.patch.HunkHeader;
import org.eclipse.jgit.patch.FileHeader.PatchType;
+import org.eclipse.jgit.patch.HunkHeader;
import org.eclipse.jgit.revwalk.FollowFilter;
import org.eclipse.jgit.revwalk.RevTree;
import org.eclipse.jgit.revwalk.RevWalk;
private int abbreviationLength = 7;
- private RawText.Factory rawTextFactory = RawText.FACTORY;
+ private RawTextComparator comparator = RawTextComparator.DEFAULT;
private int binaryFileThreshold = DEFAULT_BINARY_FILE_THRESHOLD;
}
/**
- * Set the helper that constructs difference output.
+ * Set the line equivalence function for text file differences.
*
- * @param type
- * the factory to create different output. Different types of
- * factories can produce different whitespace behavior, for
- * example.
- * @see RawText#FACTORY
- * @see RawTextIgnoreAllWhitespace#FACTORY
- * @see RawTextIgnoreLeadingWhitespace#FACTORY
- * @see RawTextIgnoreTrailingWhitespace#FACTORY
- * @see RawTextIgnoreWhitespaceChange#FACTORY
+ * @param cmp
+ * The equivalence function used to determine if two lines of
+ * text are identical. The function can be changed to ignore
+ * various types of whitespace.
+ * @see RawTextComparator#DEFAULT
+ * @see RawTextComparator#WS_IGNORE_ALL
+ * @see RawTextComparator#WS_IGNORE_CHANGE
+ * @see RawTextComparator#WS_IGNORE_LEADING
+ * @see RawTextComparator#WS_IGNORE_TRAILING
*/
- public void setRawTextFactory(RawText.Factory type) {
- rawTextFactory = type;
+ public void setDiffComparator(RawTextComparator cmp) {
+ comparator = cmp;
}
/**
type = PatchType.BINARY;
} else {
- res.a = rawTextFactory.create(aRaw);
- res.b = rawTextFactory.create(bRaw);
- editList = new MyersDiff(res.a, res.b).getEdits();
+ res.a = new RawText(comparator, aRaw);
+ res.b = new RawText(comparator, bRaw);
+ editList = diff(res.a, res.b);
type = PatchType.UNIFIED;
switch (ent.getChangeType()) {
return res;
}
+ private EditList diff(RawText a, RawText b) {
+ return new MyersDiff<RawText>(comparator, a, b).getEdits();
+ }
+
private void assertHaveRepository() {
if (db == null)
throw new IllegalStateException(JGitText.get().repositoryIsRequired);
*
* So the overall runtime complexity stays the same with linear space,
* albeit with a larger constant factor.
+ *
+ * @param <S>
+ * type of sequence.
*/
-public class MyersDiff {
+public class MyersDiff<S extends Sequence> {
/**
* The list of edits found during the last call to {@link #calculateEdits()}
*/
protected EditList edits;
+ /** Comparison function for sequences. */
+ protected SequenceComparator<S> cmp;
+
/**
* The first text to be compared. Referred to as "Text A" in the comments
*/
- protected Sequence a;
+ protected S a;
/**
* The second text to be compared. Referred to as "Text B" in the comments
*/
- protected Sequence b;
+ 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(Sequence a, Sequence b) {
+ public MyersDiff(SequenceComparator<S> cmp, S a, S b) {
+ this.cmp = cmp;
this.a = a;
this.b = b;
calculateEdits();
class ForwardEditPaths extends EditPaths {
final int snake(int k, int x) {
for (; x < endA && k + x < endB; x++)
- if (!a.equals(x, b, k + x))
+ if (!cmp.equals(a, x, b, k + x))
break;
return x;
}
class BackwardEditPaths extends EditPaths {
final int snake(int k, int x) {
for (; x > beginA && k + x > beginB; x--)
- if (!a.equals(x - 1, b, k + x - 1))
+ if (!cmp.equals(a, x - 1, b, k + x - 1))
break;
return x;
}
try {
RawText a = new RawText(new java.io.File(args[0]));
RawText b = new RawText(new java.io.File(args[1]));
- MyersDiff diff = new MyersDiff(a, b);
+ MyersDiff diff = new MyersDiff(RawTextComparator.DEFAULT, a, b);
System.out.println(diff.getEdits().toString());
} catch (Exception e) {
e.printStackTrace();
* line number 1. Callers may need to subtract 1 prior to invoking methods if
* they are converting from "line number" to "element index".
*/
-public class RawText implements Sequence {
- /** Creates a RawText instance. */
- public static interface Factory {
- /**
- * Construct a RawText instance for the content.
- *
- * @param input
- * the content array.
- * @return a RawText instance wrapping this content.
- */
- RawText create(byte[] input);
- }
-
- /** Creates RawText that does not treat whitespace specially. */
- public static final Factory FACTORY = new Factory() {
- public RawText create(byte[] input) {
- return new RawText(input);
- }
- };
-
+public class RawText extends Sequence {
/** Number of bytes to check for heuristics in {@link #isBinary(byte[])} */
private static final int FIRST_FEW_BYTES = 8000;
* through cached arrays is safe.
*/
public RawText(final byte[] input) {
+ this(RawTextComparator.DEFAULT, input);
+ }
+
+ /**
+ * Create a new sequence from an existing content byte array.
+ *
+ * The entire array (indexes 0 through length-1) is used as the content.
+ *
+ * @param cmp
+ * comparator that will later be used to compare texts.
+ * @param input
+ * the content array. The array is never modified, so passing
+ * through cached arrays is safe.
+ */
+ public RawText(RawTextComparator cmp, byte[] input) {
content = input;
lines = RawParseUtils.lineMap(content, 0, content.length);
- hashes = computeHashes();
+ hashes = computeHashes(cmp);
}
/**
this(IO.readFully(file));
}
+ /** @return total number of items in the sequence. */
public int size() {
// The line map is always 2 entries larger than the number of lines in
// the file. Index 0 is padded out/unused. The last index is the total
return lines.size() - 2;
}
- public boolean equals(final int i, final Sequence other, final int j) {
- return equals(this, i + 1, (RawText) other, j + 1);
- }
-
- private static boolean equals(final RawText a, final int ai,
- final RawText b, final int bi) {
- if (a.hashes[ai] != b.hashes[bi])
- return false;
-
- int as = a.lines.get(ai);
- int bs = b.lines.get(bi);
- final int ae = a.lines.get(ai + 1);
- final int be = b.lines.get(bi + 1);
-
- if (ae - as != be - bs)
- return false;
-
- while (as < ae) {
- if (a.content[as++] != b.content[bs++])
- return false;
- }
- return true;
- }
-
/**
* Write a specific line to the output stream, without its trailing LF.
* <p>
return content[end - 1] != '\n';
}
- private int[] computeHashes() {
+ private int[] computeHashes(RawTextComparator cmp) {
final int[] r = new int[lines.size()];
for (int lno = 1; lno < lines.size() - 1; lno++) {
final int ptr = lines.get(lno);
final int end = lines.get(lno + 1);
- r[lno] = hashLine(content, ptr, end);
+ r[lno] = cmp.hashRegion(content, ptr, end);
}
return r;
}
- /**
- * Compute a hash code for a single line.
- *
- * @param raw
- * the raw file content.
- * @param ptr
- * first byte of the content line to hash.
- * @param end
- * 1 past the last byte of the content line.
- * @return hash code for the region <code>[ptr, end)</code> of raw.
- */
- protected int hashLine(final byte[] raw, int ptr, final int end) {
- int hash = 5381;
- for (; ptr < end; ptr++)
- hash = (hash << 5) ^ (raw[ptr] & 0xff);
- return hash;
- }
-
/**
* Determine heuristically whether a byte array represents binary (as
* opposed to text) content.
--- /dev/null
+/*
+ * Copyright (C) 2009-2010, Google Inc.
+ * Copyright (C) 2008-2009, Johannes E. Schindelin <johannes.schindelin@gmx.de>
+ * 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;
+
+import static org.eclipse.jgit.util.RawCharUtil.isWhitespace;
+import static org.eclipse.jgit.util.RawCharUtil.trimLeadingWhitespace;
+import static org.eclipse.jgit.util.RawCharUtil.trimTrailingWhitespace;
+
+/** Equivalence function for {@link RawText}. */
+public abstract class RawTextComparator extends SequenceComparator<RawText> {
+ /** No special treatment. */
+ public static final RawTextComparator DEFAULT = new RawTextComparator() {
+ @Override
+ public boolean equals(RawText a, int ai, RawText b, int bi) {
+ ai++;
+ bi++;
+
+ if (a.hashes[ai] != b.hashes[bi])
+ return false;
+
+ int as = a.lines.get(ai);
+ int bs = b.lines.get(bi);
+ final int ae = a.lines.get(ai + 1);
+ final int be = b.lines.get(bi + 1);
+
+ if (ae - as != be - bs)
+ return false;
+
+ while (as < ae) {
+ if (a.content[as++] != b.content[bs++])
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashRegion(final byte[] raw, int ptr, final int end) {
+ int hash = 5381;
+ for (; ptr < end; ptr++)
+ hash = (hash << 5) ^ (raw[ptr] & 0xff);
+ return hash;
+ }
+ };
+
+ /** Ignores all whitespace. */
+ public static final RawTextComparator WS_IGNORE_ALL = new RawTextComparator() {
+ @Override
+ public boolean equals(RawText a, int ai, RawText b, int bi) {
+ ai++;
+ bi++;
+
+ if (a.hashes[ai] != b.hashes[bi])
+ return false;
+
+ int as = a.lines.get(ai);
+ int bs = b.lines.get(bi);
+ int ae = a.lines.get(ai + 1);
+ int be = b.lines.get(bi + 1);
+
+ ae = trimTrailingWhitespace(a.content, as, ae);
+ be = trimTrailingWhitespace(b.content, bs, be);
+
+ while (as < ae && bs < be) {
+ byte ac = a.content[as];
+ byte bc = b.content[bs];
+
+ while (as < ae - 1 && isWhitespace(ac)) {
+ as++;
+ ac = a.content[as];
+ }
+
+ while (bs < be - 1 && isWhitespace(bc)) {
+ bs++;
+ bc = b.content[bs];
+ }
+
+ if (ac != bc)
+ return false;
+
+ as++;
+ bs++;
+ }
+
+ return as == ae && bs == be;
+ }
+
+ @Override
+ public int hashRegion(byte[] raw, int ptr, int end) {
+ int hash = 5381;
+ for (; ptr < end; ptr++) {
+ byte c = raw[ptr];
+ if (!isWhitespace(c))
+ hash = (hash << 5) ^ (c & 0xff);
+ }
+ return hash;
+ }
+ };
+
+ /** Ignores leading whitespace. */
+ public static final RawTextComparator WS_IGNORE_LEADING = new RawTextComparator() {
+ @Override
+ public boolean equals(RawText a, int ai, RawText b, int bi) {
+ ai++;
+ bi++;
+
+ if (a.hashes[ai] != b.hashes[bi])
+ return false;
+
+ int as = a.lines.get(ai);
+ int bs = b.lines.get(bi);
+ int ae = a.lines.get(ai + 1);
+ int be = b.lines.get(bi + 1);
+
+ as = trimLeadingWhitespace(a.content, as, ae);
+ bs = trimLeadingWhitespace(b.content, bs, be);
+
+ if (ae - as != be - bs)
+ return false;
+
+ while (as < ae) {
+ if (a.content[as++] != b.content[bs++])
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashRegion(final byte[] raw, int ptr, int end) {
+ int hash = 5381;
+ ptr = trimLeadingWhitespace(raw, ptr, end);
+ for (; ptr < end; ptr++) {
+ hash = (hash << 5) ^ (raw[ptr] & 0xff);
+ }
+ return hash;
+ }
+ };
+
+ /** Ignores trailing whitespace. */
+ public static final RawTextComparator WS_IGNORE_TRAILING = new RawTextComparator() {
+ @Override
+ public boolean equals(RawText a, int ai, RawText b, int bi) {
+ ai++;
+ bi++;
+
+ if (a.hashes[ai] != b.hashes[bi])
+ return false;
+
+ int as = a.lines.get(ai);
+ int bs = b.lines.get(bi);
+ int ae = a.lines.get(ai + 1);
+ int be = b.lines.get(bi + 1);
+
+ ae = trimTrailingWhitespace(a.content, as, ae);
+ be = trimTrailingWhitespace(b.content, bs, be);
+
+ if (ae - as != be - bs)
+ return false;
+
+ while (as < ae) {
+ if (a.content[as++] != b.content[bs++])
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashRegion(final byte[] raw, int ptr, int end) {
+ int hash = 5381;
+ end = trimTrailingWhitespace(raw, ptr, end);
+ for (; ptr < end; ptr++) {
+ hash = (hash << 5) ^ (raw[ptr] & 0xff);
+ }
+ return hash;
+ }
+ };
+
+ /** Ignores trailing whitespace. */
+ public static final RawTextComparator WS_IGNORE_CHANGE = new RawTextComparator() {
+ @Override
+ public boolean equals(RawText a, int ai, RawText b, int bi) {
+ ai++;
+ bi++;
+
+ if (a.hashes[ai] != b.hashes[bi])
+ return false;
+
+ int as = a.lines.get(ai);
+ int bs = b.lines.get(bi);
+ int ae = a.lines.get(ai + 1);
+ int be = b.lines.get(bi + 1);
+
+ ae = trimTrailingWhitespace(a.content, as, ae);
+ be = trimTrailingWhitespace(b.content, bs, be);
+
+ while (as < ae && bs < be) {
+ byte ac = a.content[as];
+ byte bc = b.content[bs];
+
+ if (ac != bc)
+ return false;
+
+ if (isWhitespace(ac))
+ as = trimLeadingWhitespace(a.content, as, ae);
+ else
+ as++;
+
+ if (isWhitespace(bc))
+ bs = trimLeadingWhitespace(b.content, bs, be);
+ else
+ bs++;
+ }
+ return as == ae && bs == be;
+ }
+
+ @Override
+ public int hashRegion(final byte[] raw, int ptr, int end) {
+ int hash = 5381;
+ end = trimTrailingWhitespace(raw, ptr, end);
+ while (ptr < end) {
+ byte c = raw[ptr];
+ hash = (hash << 5) ^ (c & 0xff);
+ if (isWhitespace(c))
+ ptr = trimLeadingWhitespace(raw, ptr, end);
+ else
+ ptr++;
+ }
+ return hash;
+ }
+ };
+
+ @Override
+ public int hash(RawText seq, int ptr) {
+ return seq.hashes[ptr + 1];
+ }
+
+ /**
+ * Compute a hash code for a region.
+ *
+ * @param raw
+ * the raw file content.
+ * @param ptr
+ * first byte of the region to hash.
+ * @param end
+ * 1 past the last byte of the region.
+ * @return hash code for the region <code>[ptr, end)</code> of raw.
+ */
+ public abstract int hashRegion(byte[] raw, int ptr, int end);
+}
+++ /dev/null
-/*
- * Copyright (C) 2009-2010, Google Inc.
- * Copyright (C) 2008-2009, Johannes E. Schindelin <johannes.schindelin@gmx.de>
- * 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;
-
-import static org.eclipse.jgit.util.RawCharUtil.isWhitespace;
-import static org.eclipse.jgit.util.RawCharUtil.trimTrailingWhitespace;
-
-/**
- * A version of {@link RawText} that ignores all whitespace.
- */
-public class RawTextIgnoreAllWhitespace extends RawText {
- /** Creates RawText that ignores all whitespace. */
- @SuppressWarnings("hiding")
- public static final Factory FACTORY = new Factory() {
- public RawText create(byte[] input) {
- return new RawTextIgnoreAllWhitespace(input);
- }
- };
-
- /**
- * Create a new sequence from an existing content byte array.
- * <p>
- * The entire array (indexes 0 through length-1) is used as the content.
- *
- * @param input
- * the content array. The array is never modified, so passing
- * through cached arrays is safe.
- */
- public RawTextIgnoreAllWhitespace(byte[] input) {
- super(input);
- }
-
- @Override
- public boolean equals(final int i, final Sequence other, final int j) {
- return equals(this, i + 1, (RawText) other, j + 1);
- }
-
- private static boolean equals(final RawText a, final int ai,
- final RawText b, final int bi) {
- if (a.hashes[ai] != b.hashes[bi])
- return false;
-
- int as = a.lines.get(ai);
- int bs = b.lines.get(bi);
- int ae = a.lines.get(ai + 1);
- int be = b.lines.get(bi + 1);
-
- ae = trimTrailingWhitespace(a.content, as, ae);
- be = trimTrailingWhitespace(b.content, bs, be);
-
- while (as < ae && bs < be) {
- byte ac = a.content[as];
- byte bc = b.content[bs];
-
- while (as < ae - 1 && isWhitespace(ac)) {
- as++;
- ac = a.content[as];
- }
-
- while (bs < be - 1 && isWhitespace(bc)) {
- bs++;
- bc = b.content[bs];
- }
-
- if (ac != bc)
- return false;
-
- as++;
- bs++;
- }
-
- return as == ae && bs == be;
- }
-
- @Override
- protected int hashLine(final byte[] raw, int ptr, final int end) {
- int hash = 5381;
- for (; ptr < end; ptr++) {
- byte c = raw[ptr];
- if (!isWhitespace(c))
- hash = (hash << 5) ^ (c & 0xff);
- }
- return hash;
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2009-2010, Google Inc.
- * Copyright (C) 2008-2009, Johannes E. Schindelin <johannes.schindelin@gmx.de>
- * 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;
-
-import static org.eclipse.jgit.util.RawCharUtil.trimLeadingWhitespace;
-
-/**
- * A version of {@link RawText} that ignores leading whitespace.
- */
-public class RawTextIgnoreLeadingWhitespace extends RawText {
- /** Creates RawText that ignores only leading whitespace. */
- @SuppressWarnings("hiding")
- public static final Factory FACTORY = new Factory() {
- public RawText create(byte[] input) {
- return new RawTextIgnoreLeadingWhitespace(input);
- }
- };
-
- /**
- * Create a new sequence from an existing content byte array.
- * <p>
- * The entire array (indexes 0 through length-1) is used as the content.
- *
- * @param input
- * the content array. The array is never modified, so passing
- * through cached arrays is safe.
- */
- public RawTextIgnoreLeadingWhitespace(byte[] input) {
- super(input);
- }
-
- @Override
- public boolean equals(final int i, final Sequence other, final int j) {
- return equals(this, i + 1, (RawText) other, j + 1);
- }
-
- private static boolean equals(final RawText a, final int ai,
- final RawText b, final int bi) {
- if (a.hashes[ai] != b.hashes[bi])
- return false;
-
- int as = a.lines.get(ai);
- int bs = b.lines.get(bi);
- int ae = a.lines.get(ai + 1);
- int be = b.lines.get(bi + 1);
-
- as = trimLeadingWhitespace(a.content, as, ae);
- bs = trimLeadingWhitespace(b.content, bs, be);
-
- if (ae - as != be - bs)
- return false;
-
- while (as < ae) {
- if (a.content[as++] != b.content[bs++])
- return false;
- }
- return true;
- }
-
- @Override
- protected int hashLine(final byte[] raw, int ptr, int end) {
- int hash = 5381;
- ptr = trimLeadingWhitespace(raw, ptr, end);
- for (; ptr < end; ptr++) {
- hash = (hash << 5) ^ (raw[ptr] & 0xff);
- }
- return hash;
- }
-}
\ No newline at end of file
+++ /dev/null
-/*
- * Copyright (C) 2009-2010, Google Inc.
- * Copyright (C) 2008-2009, Johannes E. Schindelin <johannes.schindelin@gmx.de>
- * 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;
-
-import static org.eclipse.jgit.util.RawCharUtil.trimTrailingWhitespace;
-
-/**
- * A version of {@link RawText} that ignores trailing whitespace.
- */
-public class RawTextIgnoreTrailingWhitespace extends RawText {
- /** Creates RawText that ignores only trailing whitespace. */
- @SuppressWarnings("hiding")
- public static final Factory FACTORY = new Factory() {
- public RawText create(byte[] input) {
- return new RawTextIgnoreTrailingWhitespace(input);
- }
- };
-
- /**
- * Create a new sequence from an existing content byte array.
- * <p>
- * The entire array (indexes 0 through length-1) is used as the content.
- *
- * @param input
- * the content array. The array is never modified, so passing
- * through cached arrays is safe.
- */
- public RawTextIgnoreTrailingWhitespace(byte[] input) {
- super(input);
- }
-
- @Override
- public boolean equals(final int i, final Sequence other, final int j) {
- return equals(this, i + 1, (RawText) other, j + 1);
- }
-
- private static boolean equals(final RawText a, final int ai,
- final RawText b, final int bi) {
- if (a.hashes[ai] != b.hashes[bi])
- return false;
-
- int as = a.lines.get(ai);
- int bs = b.lines.get(bi);
- int ae = a.lines.get(ai + 1);
- int be = b.lines.get(bi + 1);
-
- ae = trimTrailingWhitespace(a.content, as, ae);
- be = trimTrailingWhitespace(b.content, bs, be);
-
- if (ae - as != be - bs)
- return false;
-
- while (as < ae) {
- if (a.content[as++] != b.content[bs++])
- return false;
- }
- return true;
- }
-
- @Override
- protected int hashLine(final byte[] raw, int ptr, int end) {
- int hash = 5381;
- end = trimTrailingWhitespace(raw, ptr, end);
- for (; ptr < end; ptr++) {
- hash = (hash << 5) ^ (raw[ptr] & 0xff);
- }
- return hash;
- }
-}
\ No newline at end of file
+++ /dev/null
-/*
- * Copyright (C) 2009-2010, Google Inc.
- * Copyright (C) 2008-2009, Johannes E. Schindelin <johannes.schindelin@gmx.de>
- * 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;
-
-import static org.eclipse.jgit.util.RawCharUtil.isWhitespace;
-import static org.eclipse.jgit.util.RawCharUtil.trimLeadingWhitespace;
-import static org.eclipse.jgit.util.RawCharUtil.trimTrailingWhitespace;
-
-/**
- * A version of {@link RawText} that ignores changes in the amount of
- * whitespace, as well as trailing whitespace.
- */
-public class RawTextIgnoreWhitespaceChange extends RawText {
- /** Creates RawText that ignores only whitespace changes. */
- @SuppressWarnings("hiding")
- public static final Factory FACTORY = new Factory() {
- public RawText create(byte[] input) {
- return new RawTextIgnoreWhitespaceChange(input);
- }
- };
-
- /**
- * Create a new sequence from an existing content byte array.
- * <p>
- * The entire array (indexes 0 through length-1) is used as the content.
- *
- * @param input
- * the content array. The array is never modified, so passing
- * through cached arrays is safe.
- */
- public RawTextIgnoreWhitespaceChange(byte[] input) {
- super(input);
- }
-
- @Override
- public boolean equals(final int i, final Sequence other, final int j) {
- return equals(this, i + 1, (RawText) other, j + 1);
- }
-
- private static boolean equals(final RawText a, final int ai,
- final RawText b, final int bi) {
- if (a.hashes[ai] != b.hashes[bi])
- return false;
-
- int as = a.lines.get(ai);
- int bs = b.lines.get(bi);
- int ae = a.lines.get(ai + 1);
- int be = b.lines.get(bi + 1);
-
- ae = trimTrailingWhitespace(a.content, as, ae);
- be = trimTrailingWhitespace(b.content, bs, be);
-
- while (as < ae && bs < be) {
- byte ac = a.content[as];
- byte bc = b.content[bs];
-
- if (ac != bc)
- return false;
-
- if (isWhitespace(ac))
- as = trimLeadingWhitespace(a.content, as, ae);
- else
- as++;
-
- if (isWhitespace(bc))
- bs = trimLeadingWhitespace(b.content, bs, be);
- else
- bs++;
- }
- return as == ae && bs == be;
- }
-
- @Override
- protected int hashLine(final byte[] raw, int ptr, int end) {
- int hash = 5381;
- end = trimTrailingWhitespace(raw, ptr, end);
- while (ptr < end) {
- byte c = raw[ptr];
- hash = (hash << 5) ^ (c & 0xff);
- if (isWhitespace(c))
- ptr = trimLeadingWhitespace(raw, ptr, end);
- else
- ptr++;
- }
- return hash;
- }
-}
\ No newline at end of file
/*
+ * Copyright (C) 2010, Google Inc.
* Copyright (C) 2008-2009, Johannes E. Schindelin <johannes.schindelin@gmx.de>
* and other copyright owners as documented in the project's IP log.
*
package org.eclipse.jgit.diff;
/**
- * Arbitrary sequence of elements with fast comparison support.
- * <p>
+ * Arbitrary sequence of elements.
+ *
* A sequence of elements is defined to contain elements in the index range
* <code>[0, {@link #size()})</code>, like a standard Java List implementation.
- * Unlike a List, the members of the sequence are not directly obtainable, but
- * element equality can be tested if two Sequences are the same implementation.
- * <p>
- * An implementation may chose to implement the equals semantic as necessary,
- * including fuzzy matching rules such as ignoring insignificant sub-elements,
- * e.g. ignoring whitespace differences in text.
- * <p>
+ * Unlike a List, the members of the sequence are not directly obtainable.
+ *
* Implementations of Sequence are primarily intended for use in content
* difference detection algorithms, to produce an {@link EditList} of
* {@link Edit} instances describing how two Sequence instances differ.
+ *
+ * To be compared against another Sequence of the same type, a supporting
+ * {@link SequenceComparator} must also be supplied.
*/
-public interface Sequence {
+public abstract class Sequence {
/** @return total number of items in the sequence. */
- public int size();
-
- /**
- * Determine if the i-th member is equal to the j-th member.
- * <p>
- * Implementations must ensure <code>equals(thisIdx,other,otherIdx)</code>
- * returns the same as <code>other.equals(otherIdx,this,thisIdx)</code>.
- *
- * @param thisIdx
- * index within <code>this</code> sequence; must be in the range
- * <code>[ 0, this.size() )</code>.
- * @param other
- * another sequence; must be the same implementation class, that
- * is <code>this.getClass() == other.getClass()</code>.
- * @param otherIdx
- * index within <code>other</code> sequence; must be in the range
- * <code>[ 0, other.size() )</code>.
- * @return true if the elements are equal; false if they are not equal.
- */
- public boolean equals(int thisIdx, Sequence other, int otherIdx);
+ public abstract int size();
}
--- /dev/null
+/*
+ * 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;
+
+/**
+ * Equivalence function for a {@link Sequence} compared by difference algorithm.
+ *
+ * Difference algorithms can use a comparator to compare portions of two
+ * sequences and discover the minimal edits required to transform from one
+ * sequence to the other sequence.
+ *
+ * Indexes within a sequence are zero-based.
+ *
+ * @param <S>
+ * type of sequence the comparator supports.
+ */
+public abstract class SequenceComparator<S extends Sequence> {
+ /**
+ * Compare two items to determine if they are equivalent.
+ *
+ * It is permissible to compare sequence {@code a} with itself (by passing
+ * {@code a} again in position {@code b}).
+ *
+ * @param a
+ * the first sequence.
+ * @param ai
+ * item of {@code ai} to compare.
+ * @param b
+ * the second sequence.
+ * @param bi
+ * item of {@code bi} to compare.
+ * @return true if the two items are identical according to this function's
+ * equivalence rule.
+ */
+ public abstract boolean equals(S a, int ai, S b, int bi);
+
+ /**
+ * Get a hash value for an item in a sequence.
+ *
+ * If two items are equal according to this comparator's
+ * {@link #equals(Sequence, int, Sequence, int)} method, then this hash
+ * method must produce the same integer result for both items.
+ *
+ * It is not required for two items to have different hash values if they
+ * are are unequal according to the {@code equals()} method.
+ *
+ * @param seq
+ * the sequence.
+ * @param ptr
+ * the item to obtain the hash for.
+ * @return hash the hash value.
+ */
+ public abstract int hash(S seq, int ptr);
+}
import org.eclipse.jgit.diff.EditList;
import org.eclipse.jgit.diff.MyersDiff;
import org.eclipse.jgit.diff.Sequence;
+import org.eclipse.jgit.diff.SequenceComparator;
import org.eclipse.jgit.merge.MergeChunk.ConflictState;
/**
/**
* Does the three way merge between a common base and two sequences.
*
+ * @param <S>
+ * type of sequence.
+ * @param cmp comparison method for this execution.
* @param base the common base sequence
* @param ours the first sequence to be merged
* @param theirs the second sequence to be merged
* @return the resulting content
*/
- public static MergeResult merge(Sequence base, Sequence ours,
- Sequence theirs) {
- List<Sequence> sequences = new ArrayList<Sequence>(3);
+ public static <S extends Sequence> MergeResult<S> merge(
+ SequenceComparator<S> cmp, S base, S ours, S theirs) {
+ List<S> sequences = new ArrayList<S>(3);
sequences.add(base);
sequences.add(ours);
sequences.add(theirs);
- MergeResult result = new MergeResult(sequences);
- EditList oursEdits = new MyersDiff(base, ours).getEdits();
+ MergeResult result = new MergeResult<S>(sequences);
+ EditList oursEdits = new MyersDiff<S>(cmp, base, ours).getEdits();
Iterator<Edit> baseToOurs = oursEdits.iterator();
- EditList theirsEdits = new MyersDiff(base, theirs).getEdits();
+ EditList theirsEdits = new MyersDiff<S>(cmp, base, theirs).getEdits();
Iterator<Edit> baseToTheirs = theirsEdits.iterator();
int current = 0; // points to the next line (first line is 0) of base
// which was not handled yet
- theirsBeginB);
int commonPrefix = 0;
while (commonPrefix < conflictLen
- && ours.equals(oursBeginB + commonPrefix, theirs,
+ && cmp.equals(ours, oursBeginB + commonPrefix, theirs,
theirsBeginB + commonPrefix))
commonPrefix++;
conflictLen -= commonPrefix;
int commonSuffix = 0;
while (commonSuffix < conflictLen
- && ours.equals(oursEndB - commonSuffix - 1, theirs,
+ && cmp.equals(ours, oursEndB - commonSuffix - 1, theirs,
theirsEndB - commonSuffix - 1))
commonSuffix++;
conflictLen -= commonSuffix;
* metadata
* @throws IOException
*/
- public void formatMerge(OutputStream out, MergeResult res,
+ public void formatMerge(OutputStream out, MergeResult<RawText> res,
List<String> seqName, String charsetName) throws IOException {
String lastConflictingName = null; // is set to non-null whenever we are
// in a conflict
boolean threeWayMerge = (res.getSequences().size() == 3);
for (MergeChunk chunk : res) {
- RawText seq = (RawText) res.getSequences().get(
- chunk.getSequenceIndex());
+ RawText seq = res.getSequences().get(chunk.getSequenceIndex());
if (lastConflictingName != null
&& chunk.getConflictState() != ConflictState.NEXT_CONFLICTING_RANGE) {
// found the end of an conflict
* This class does not know anything about how to present the merge result to
* the end-user. MergeFormatters have to be used to construct something human
* readable.
+ *
+ * @param <S>
+ * type of sequence.
*/
-public class MergeResult implements Iterable<MergeChunk> {
- private final List<Sequence> sequences;
+public class MergeResult<S extends Sequence> implements Iterable<MergeChunk> {
+ private final List<S> sequences;
private final IntList chunks = new IntList();
* followed by the merged sequences. This list should not be
* modified anymore during the lifetime of this {@link MergeResult}.
*/
- public MergeResult(List<Sequence> sequences) {
+ public MergeResult(List<S> sequences) {
this.sequences = sequences;
}
* @return the common predecessor at position 0 followed by the merged
* sequences.
*/
- public List<Sequence> getSequences() {
+ public List<S> getSequences() {
return sequences;
}
import org.eclipse.jgit.JGitText;
import org.eclipse.jgit.diff.RawText;
+import org.eclipse.jgit.diff.RawTextComparator;
+import org.eclipse.jgit.diff.Sequence;
import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheBuildIterator;
import org.eclipse.jgit.dircache.DirCacheBuilder;
private Map<String, DirCacheEntry> toBeCheckedOut = new HashMap<String, DirCacheEntry>();
- private Map<String, MergeResult> mergeResults = new HashMap<String, MergeResult>();
+ private Map<String, MergeResult<? extends Sequence>> mergeResults = new HashMap<String, MergeResult<? extends Sequence>>();
private Map<String, MergeFailureReason> failingPathes = new HashMap<String, MergeFailureReason>();
MergeFormatter fmt = new MergeFormatter();
// do the merge
- MergeResult result = MergeAlgorithm.merge(
+ MergeResult<RawText> result = MergeAlgorithm.merge(
+ RawTextComparator.DEFAULT,
getRawText(base.getEntryObjectId(), db),
getRawText(ours.getEntryObjectId(), db),
getRawText(theirs.getEntryObjectId(), db));
/**
* @return the mergeResults
*/
- public Map<String, MergeResult> getMergeResults() {
+ public Map<String, MergeResult<? extends Sequence>> getMergeResults() {
return mergeResults;
}