]> source.dussan.org Git - jgit.git/commitdiff
Refactor diff sequence API 02/1502/6
authorShawn O. Pearce <spearce@spearce.org>
Thu, 2 Sep 2010 19:53:27 +0000 (12:53 -0700)
committerChris Aniszczyk <caniszczyk@gmail.com>
Tue, 7 Sep 2010 02:37:11 +0000 (21:37 -0500)
Instead of making the sequence itself responsible for the equivalence
function, use an external function that is supplied by the caller.
This cleans up the code because we now say cmp.equals(a, ai, b, bi)
instead of a.equals(ai, b, bi).

This refactoring also removes the odd concept of creating different
types of sequences to have different behaviors for whitespace
ignoring.  Instead DiffComparator now supports singleton functions
that apply a particular equivalence algorithm to a type of sequence.

Change-Id: I559f494d81cdc6f06bfb4208f60780c0ae251df9
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
27 files changed:
org.eclipse.jgit.iplog/src/org/eclipse/jgit/iplog/IpLogGenerator.java
org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Diff.java
org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Log.java
org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/MyersDiffPerformanceTest.java
org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/MyersDiffTest.java
org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/RawTextIgnoreAllWhitespaceTest.java
org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/RawTextIgnoreLeadingWhitespaceTest.java
org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/RawTextIgnoreTrailingWhitespaceTest.java
org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/RawTextIgnoreWhitespaceChangeTest.java
org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/RawTextTest.java
org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/MergeAlgorithmTest.java
org.eclipse.jgit/src/org/eclipse/jgit/api/MergeCommand.java
org.eclipse.jgit/src/org/eclipse/jgit/api/MergeResult.java
org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java
org.eclipse.jgit/src/org/eclipse/jgit/diff/MyersDiff.java
org.eclipse.jgit/src/org/eclipse/jgit/diff/RawText.java
org.eclipse.jgit/src/org/eclipse/jgit/diff/RawTextComparator.java [new file with mode: 0644]
org.eclipse.jgit/src/org/eclipse/jgit/diff/RawTextIgnoreAllWhitespace.java [deleted file]
org.eclipse.jgit/src/org/eclipse/jgit/diff/RawTextIgnoreLeadingWhitespace.java [deleted file]
org.eclipse.jgit/src/org/eclipse/jgit/diff/RawTextIgnoreTrailingWhitespace.java [deleted file]
org.eclipse.jgit/src/org/eclipse/jgit/diff/RawTextIgnoreWhitespaceChange.java [deleted file]
org.eclipse.jgit/src/org/eclipse/jgit/diff/Sequence.java
org.eclipse.jgit/src/org/eclipse/jgit/diff/SequenceComparator.java [new file with mode: 0644]
org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeAlgorithm.java
org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeFormatter.java
org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeResult.java
org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java

index 433d4338df59b62e303b63815b9dd7562b326432..5013eb6b8a9e77de3dfd61f77749ac01d44a552a 100644 (file)
@@ -77,6 +77,7 @@ import org.eclipse.jgit.diff.Edit;
 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;
@@ -383,7 +384,8 @@ public class IpLogGenerator {
                                        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();
index 7a4aed71ea586478fa718c3d8237510dfae08ffb..a5f801b296550500fa1bd58660e6e359a7b791b6 100644 (file)
@@ -55,10 +55,7 @@ import java.util.List;
 
 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;
@@ -109,22 +106,22 @@ class Diff extends TextBuiltin {
 
        @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")
index 92cb70d4c4c8900fd20c30e552176982e4b76135..0ce774b27db2ca17164807d9810a3576c660c953 100644 (file)
@@ -58,10 +58,7 @@ import java.util.Set;
 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;
@@ -106,22 +103,22 @@ class Log extends RevWalkTextBuiltin {
 
        @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")
index b97c1633f714425e678a06bc551978ea9e30b5aa..38fac3cc969c8f2b213ccb9a2e8ee9022fa4f634 100644 (file)
@@ -163,14 +163,15 @@ public class MyersDiffPerformanceTest extends TestCase {
                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) {
@@ -179,26 +180,34 @@ public class MyersDiffPerformanceTest extends TestCase {
                        }
                }
                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];
                }
        }
 }
index c91348ffe63ad835c0c3b7e9179a267f1bd1f08f..60c1b47280e361186ef29608c5b82da8ef8284d7 100644 (file)
@@ -63,7 +63,8 @@ public class MyersDiffTest extends TestCase {
        }
 
        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()));
        }
 
@@ -80,8 +81,7 @@ public class MyersDiffTest extends TestCase {
                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);
        }
 
@@ -97,13 +97,21 @@ public class MyersDiffTest extends TestCase {
                        + ")";
        }
 
-       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];
                }
        }
 }
index 5e1a238a72faaf3edade0d1a7902f035b6fa4553..c59f3780b1ff35fd95edd15d055ba93c5160b3ad 100644 (file)
@@ -49,48 +49,50 @@ import org.eclipse.jgit.lib.Constants;
 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));
        }
 }
index 9ab18873dc882becda78577e3811db43239e211e..647fa30d2e7eb36512fe4bf05d159f2bb8b9bc2b 100644 (file)
@@ -49,52 +49,54 @@ import org.eclipse.jgit.lib.Constants;
 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));
        }
 }
index ad6a2397be436cc4bce247a682c6eca86fe1cdb7..b6999cd031e913d6999cfef3bb26a7305dd100a0 100644 (file)
@@ -49,52 +49,54 @@ import org.eclipse.jgit.lib.Constants;
 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));
        }
 }
index 4a71c44885abe84e9c661a6609fec7bcf61a2b80..62a079f395fc5346877f10432144054c2e58d128 100644 (file)
@@ -49,57 +49,58 @@ import org.eclipse.jgit.lib.Constants;
 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));
        }
 }
index 5cb8bc394597f4ac6d1b702b97655e43c05e814a..f30e07f22dfcedd58eb60a2b725be8216de6344a 100644 (file)
@@ -61,17 +61,18 @@ public class RawTextTest extends TestCase {
        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 {
index 1ccc00ecabcea234cd4e856ab6d4881d4cadab3f..47f3292515a954d15f1f0037162951428f6f1134 100644 (file)
@@ -49,6 +49,7 @@ import java.io.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 {
@@ -190,7 +191,7 @@ 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);
index b2e0175e36852f3c2797b3c3b0e223e1d409caf6..c636ff7ffc05de8abfe6a5fbe291454446c27dac 100644 (file)
@@ -173,7 +173,7 @@ public class MergeCommand extends GitCommand<MergeResult> {
                                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;
index ddb14a03fcdd9bfc08146b853b93afe0519641cd..2099352f5f9ed543a9b8fb61395845d86d21a041 100644 (file)
@@ -134,7 +134,7 @@ public class MergeResult {
         */
        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);
        }
@@ -160,7 +160,7 @@ public class MergeResult {
        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;
@@ -243,7 +243,7 @@ public class MergeResult {
         * @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;
index 8e92c8995cf367fd2be1313aadd3d522c3ea967e..e36aaf17fb299a1adc717becdc826995711fe689 100644 (file)
@@ -78,8 +78,8 @@ import org.eclipse.jgit.lib.ObjectReader;
 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;
@@ -118,7 +118,7 @@ public class DiffFormatter {
 
        private int abbreviationLength = 7;
 
-       private RawText.Factory rawTextFactory = RawText.FACTORY;
+       private RawTextComparator comparator = RawTextComparator.DEFAULT;
 
        private int binaryFileThreshold = DEFAULT_BINARY_FILE_THRESHOLD;
 
@@ -207,20 +207,20 @@ public class DiffFormatter {
        }
 
        /**
-        * 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;
        }
 
        /**
@@ -869,9 +869,9 @@ public class DiffFormatter {
                                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()) {
@@ -892,6 +892,10 @@ public class DiffFormatter {
                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);
index 6a4b44bff18b16b6c54a488080a1d5cffff06321..270ed92743f8908579eb80d7a660b5ad2f3f1969 100644 (file)
@@ -101,30 +101,38 @@ import org.eclipse.jgit.util.LongList;
  *
  * 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();
@@ -436,7 +444,7 @@ if (k < beginK || k > endK)
                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;
                        }
@@ -478,7 +486,7 @@ if (k < beginK || k > endK)
                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;
                        }
@@ -529,7 +537,7 @@ if (k < beginK || k > endK)
                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();
index ad81de58c9a045fb3a49a8433b266f51bba7c657..07d28572ad40c6a04557e3dc19e0a6199b0fd8d1 100644 (file)
@@ -65,26 +65,7 @@ import org.eclipse.jgit.util.RawParseUtils;
  * 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;
 
@@ -107,9 +88,24 @@ public class RawText implements Sequence {
         *            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);
        }
 
        /**
@@ -126,6 +122,7 @@ public class RawText implements Sequence {
                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
@@ -134,30 +131,6 @@ public class RawText implements Sequence {
                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>
@@ -197,34 +170,16 @@ public class RawText implements Sequence {
                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.
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/RawTextComparator.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/RawTextComparator.java
new file mode 100644 (file)
index 0000000..2f31618
--- /dev/null
@@ -0,0 +1,290 @@
+/*
+ * 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);
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/RawTextIgnoreAllWhitespace.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/RawTextIgnoreAllWhitespace.java
deleted file mode 100644 (file)
index 855a872..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * 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;
-       }
-}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/RawTextIgnoreLeadingWhitespace.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/RawTextIgnoreLeadingWhitespace.java
deleted file mode 100644 (file)
index df4805a..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * 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
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/RawTextIgnoreTrailingWhitespace.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/RawTextIgnoreTrailingWhitespace.java
deleted file mode 100644 (file)
index 5e69eaa..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * 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
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/RawTextIgnoreWhitespaceChange.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/RawTextIgnoreWhitespaceChange.java
deleted file mode 100644 (file)
index 2d1b977..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * 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
index 34f3f443f1e25a0333d82640de485d9e4157bf2d..4e01c17da545afbbb002c9745365cc717e568b1a 100644 (file)
@@ -1,4 +1,5 @@
 /*
+ * 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();
 }
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/SequenceComparator.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/SequenceComparator.java
new file mode 100644 (file)
index 0000000..5ec2351
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * 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);
+}
index 2c8386b8c25bc2aedee88b2a22755dc32f9b8142..a2a0ee6abd29e580fcfecc6d0cb3bd6cd9bf60fc 100644 (file)
@@ -51,6 +51,7 @@ import org.eclipse.jgit.diff.Edit;
 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;
 
 /**
@@ -74,21 +75,24 @@ public final class MergeAlgorithm {
        /**
         * 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
@@ -201,13 +205,13 @@ public final class MergeAlgorithm {
                                                - 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;
index 2ff3e9b6552de05ffb4f3ca5f72be59b88fc0c4b..5feb3a859b3f1dc8e36f7f0c7e6633d0b07d025f 100644 (file)
@@ -76,14 +76,13 @@ public class MergeFormatter {
         *            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
index 0da487bc66ec1b376ebf2216c8918a1a536c4951..2dd4426e1164648c5e8efe8a2d9697bbd40c5ca7 100644 (file)
@@ -63,9 +63,12 @@ import org.eclipse.jgit.util.IntList;
  * 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();
 
@@ -79,7 +82,7 @@ public class MergeResult implements Iterable<MergeChunk> {
         *            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;
        }
 
@@ -120,7 +123,7 @@ public class MergeResult implements Iterable<MergeChunk> {
         * @return the common predecessor at position 0 followed by the merged
         *         sequences.
         */
-       public List<Sequence> getSequences() {
+       public List<S> getSequences() {
                return sequences;
        }
 
index a69396a57274037e0c41b4c4745e7d97f81be3d6..42f9849ee73a3bb1e5a4ea76e9b77e5464febc35 100644 (file)
@@ -59,6 +59,8 @@ import java.util.Map;
 
 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;
@@ -118,7 +120,7 @@ public class ResolveMerger extends ThreeWayMerger {
 
        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>();
 
@@ -413,7 +415,8 @@ public class ResolveMerger extends ThreeWayMerger {
                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));
@@ -524,7 +527,7 @@ public class ResolveMerger extends ThreeWayMerger {
        /**
         * @return the mergeResults
         */
-       public Map<String, MergeResult> getMergeResults() {
+       public Map<String, MergeResult<? extends Sequence>> getMergeResults() {
                return mergeResults;
        }