{"thread":{"id":"12279","subject":"[EGIT] Sort order from hell fixes, take 2","startedAt":"2008-02-23T23:50:33Z","lastAt":"2008-03-03T14:17:04Z","messageCount":12,"participants":["Robin Rosenberg","David Watson"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"69742","messageId":"1203810643-28819-1-git-send-email-robin.rosenberg@dewire.com","threadId":"12279","inReplyTo":null,"subject":"[EGIT] Sort order from hell fixes, take 2","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg@dewire.com","sentAt":"2008-02-23T23:50:33Z","receivedAt":"2008-02-23T23:50:33Z","isPatch":false,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"Hi fans,\n\nMy previous attempt to fix this failed, so here is another round, including\nsome new infrastructure like a TreeIterator to support this fix and whatever\nwill need it.\n\nFeed free to scrutize and invent whatever evil test case might be missing.\n\nThe reason I noticed the problem was introduced in c20142, where the unit\ntests for org.spearce.jgit was moved to the new project org.spearce.jgit.test .\n\n-- robin\n"},{"id":"69743","messageId":"1203810643-28819-2-git-send-email-robin.rosenberg@dewire.com","threadId":"12279","inReplyTo":"1203810643-28819-1-git-send-email-robin.rosenberg@dewire.com","subject":"[EGIT PATCH 01/10] Tighten IndexDiffTest to make it test better what it claims to test","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg@dewire.com","sentAt":"2008-02-23T23:50:34Z","receivedAt":"2008-02-23T23:50:34Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"I.e. test more of the expected state\n\nSigned-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>\n---\n .../tst/org/spearce/jgit/lib/IndexDiffTest.java    |   22 ++++++++++++++++++++\n 1 files changed, 22 insertions(+), 0 deletions(-)\n\ndiff --git a/org.spearce.jgit.test/tst/org/spearce/jgit/lib/IndexDiffTest.java b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/IndexDiffTest.java\nindex ba5d8d7..629c06c 100644\n--- a/org.spearce.jgit.test/tst/org/spearce/jgit/lib/IndexDiffTest.java\n+++ b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/IndexDiffTest.java\n@@ -31,8 +31,12 @@ public class IndexDiffTest extends RepositoryTestCase {\n \t\tindex.add(trash, new File(trash, \"dir/subfile\"));\n \t\tIndexDiff diff = new IndexDiff(tree, index);\n \t\tdiff.diff();\n+\t\tassertEquals(2, diff.getAdded().size());\n \t\tassertTrue(diff.getAdded().contains(\"file1\"));\n \t\tassertTrue(diff.getAdded().contains(\"dir/subfile\"));\n+\t\tassertEquals(0, diff.getChanged().size());\n+\t\tassertEquals(0, diff.getModified().size());\n+\t\tassertEquals(0, diff.getRemoved().size());\n \t}\n \n \tpublic void testRemoved() throws IOException {\n@@ -44,11 +48,20 @@ public class IndexDiffTest extends RepositoryTestCase {\n \t\ttree.addFile(\"file2\");\n \t\ttree.addFile(\"dir/file3\");\n \t\tassertEquals(2, tree.memberCount());\n+\t\ttree.findBlobMember(\"file2\").setId(new ObjectId(\"30d67d4672d5c05833b7192cc77a79eaafb5c7ad\"));\n+\t\tTree tree2 = (Tree) tree.findTreeMember(\"dir\");\n+\t\ttree2.findBlobMember(\"file3\").setId(new ObjectId(\"873fb8d667d05436d728c52b1d7a09528e6eb59b\"));\n+\t\ttree2.setId(new ObjectWriter(db).writeTree(tree2));\n+\t\ttree.setId(new ObjectWriter(db).writeTree(tree));\n \n \t\tIndexDiff diff = new IndexDiff(tree, index);\n \t\tdiff.diff();\n+\t\tassertEquals(2, diff.getRemoved().size());\n \t\tassertTrue(diff.getRemoved().contains(\"file2\"));\n \t\tassertTrue(diff.getRemoved().contains(\"dir/file3\"));\n+\t\tassertEquals(0, diff.getChanged().size());\n+\t\tassertEquals(0, diff.getModified().size());\n+\t\tassertEquals(0, diff.getAdded().size());\n \t}\n \n \tpublic void testModified() throws IOException {\n@@ -65,10 +78,19 @@ public class IndexDiffTest extends RepositoryTestCase {\n \t\ttree.addFile(\"dir/file3\").setId(new ObjectId(\"0123456789012345678901234567890123456789\"));\n \t\tassertEquals(2, tree.memberCount());\n \n+\t\tTree tree2 = (Tree) tree.findTreeMember(\"dir\");\n+\t\ttree2.setId(new ObjectWriter(db).writeTree(tree2));\n+\t\ttree.setId(new ObjectWriter(db).writeTree(tree));\n \t\tIndexDiff diff = new IndexDiff(tree, index);\n \t\tdiff.diff();\n+\t\tassertEquals(2, diff.getChanged().size());\n \t\tassertTrue(diff.getChanged().contains(\"file2\"));\n \t\tassertTrue(diff.getChanged().contains(\"dir/file3\"));\n+\t\tassertEquals(1, diff.getModified().size());\n \t\tassertTrue(diff.getModified().contains(\"dir/file3\"));\n+\t\tassertEquals(0, diff.getAdded().size());\n+\t\tassertEquals(0, diff.getRemoved().size());\n+\t\tassertEquals(0, diff.getMissing().size());\n \t}\n+\n }\n-- \n1.5.4.2\n"},{"id":"69749","messageId":"1203810643-28819-3-git-send-email-robin.rosenberg@dewire.com","threadId":"12279","inReplyTo":"1203810643-28819-2-git-send-email-robin.rosenberg@dewire.com","subject":"[EGIT PATCH 02/10] Extend IndexDiffTest with more tests","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg@dewire.com","sentAt":"2008-02-23T23:50:35Z","receivedAt":"2008-02-23T23:50:35Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"This adds tests for some nasty cases. These can be summarized\nby declaring that this is the correct order:\n\n\ta.b\n\ta/b\n\ta=b\n\nSigned-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>\n---\n .../tst/org/spearce/jgit/lib/IndexDiffTest.java    |   67 ++++++++++++++++++++\n 1 files changed, 67 insertions(+), 0 deletions(-)\n\ndiff --git a/org.spearce.jgit.test/tst/org/spearce/jgit/lib/IndexDiffTest.java b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/IndexDiffTest.java\nindex 629c06c..4692fa2 100644\n--- a/org.spearce.jgit.test/tst/org/spearce/jgit/lib/IndexDiffTest.java\n+++ b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/IndexDiffTest.java\n@@ -93,4 +93,71 @@ public class IndexDiffTest extends RepositoryTestCase {\n \t\tassertEquals(0, diff.getMissing().size());\n \t}\n \n+\tpublic void testUnchangedSimple() throws IOException {\n+\t\tGitIndex index = new GitIndex(db);\n+\n+\t\tindex.add(trash, writeTrashFile(\"a.b\", \"a.b\"));\n+\t\tindex.add(trash, writeTrashFile(\"a.c\", \"a.c\"));\n+\t\tindex.add(trash, writeTrashFile(\"a=c\", \"a=c\"));\n+\t\tindex.add(trash, writeTrashFile(\"a=d\", \"a=d\"));\n+\n+\t\tTree tree = new Tree(db);\n+\t\t// got the hash id'd from the data using echo -n a.b|git hash-object -t blob --stdin\n+\t\ttree.addFile(\"a.b\").setId(new ObjectId(\"f6f28df96c2b40c951164286e08be7c38ec74851\"));\n+\t\ttree.addFile(\"a.c\").setId(new ObjectId(\"6bc0e647512d2a0bef4f26111e484dc87df7f5ca\"));\n+\t\ttree.addFile(\"a=c\").setId(new ObjectId(\"06022365ddbd7fb126761319633bf73517770714\"));\n+\t\ttree.addFile(\"a=d\").setId(new ObjectId(\"fa6414df3da87840700e9eeb7fc261dd77ccd5c2\"));\n+\n+\t\ttree.setId(new ObjectWriter(db).writeTree(tree));\n+\n+\t\tIndexDiff diff = new IndexDiff(tree, index);\n+\t\tdiff.diff();\n+\t\tassertEquals(0, diff.getChanged().size());\n+\t\tassertEquals(0, diff.getAdded().size());\n+\t\tassertEquals(0, diff.getRemoved().size());\n+\t\tassertEquals(0, diff.getMissing().size());\n+\t\tassertEquals(0, diff.getModified().size());\n+\t}\n+\n+\t/**\n+\t * This test has both files and directories that involve\n+\t * the tricky ordering used by Git.\n+\t *\n+\t * @throws IOException\n+\t */\n+\tpublic void testUnchangedComplex() throws IOException {\n+\t\tGitIndex index = new GitIndex(db);\n+\n+\t\tindex.add(trash, writeTrashFile(\"a.b\", \"a.b\"));\n+\t\tindex.add(trash, writeTrashFile(\"a.c\", \"a.c\"));\n+\t\tindex.add(trash, writeTrashFile(\"a/b.b/b\", \"a/b.b/b\"));\n+\t\tindex.add(trash, writeTrashFile(\"a/b\", \"a/b\"));\n+\t\tindex.add(trash, writeTrashFile(\"a/c\", \"a/c\"));\n+\t\tindex.add(trash, writeTrashFile(\"a=c\", \"a=c\"));\n+\t\tindex.add(trash, writeTrashFile(\"a=d\", \"a=d\"));\n+\n+\t\tTree tree = new Tree(db);\n+\t\t// got the hash id'd from the data using echo -n a.b|git hash-object -t blob --stdin\n+\t\ttree.addFile(\"a.b\").setId(new ObjectId(\"f6f28df96c2b40c951164286e08be7c38ec74851\"));\n+\t\ttree.addFile(\"a.c\").setId(new ObjectId(\"6bc0e647512d2a0bef4f26111e484dc87df7f5ca\"));\n+\t\ttree.addFile(\"a/b.b/b\").setId(new ObjectId(\"8d840bd4e2f3a48ff417c8e927d94996849933fd\"));\n+\t\ttree.addFile(\"a/b\").setId(new ObjectId(\"db89c972fc57862eae378f45b74aca228037d415\"));\n+\t\ttree.addFile(\"a/c\").setId(new ObjectId(\"52ad142a008aeb39694bafff8e8f1be75ed7f007\"));\n+\t\ttree.addFile(\"a=c\").setId(new ObjectId(\"06022365ddbd7fb126761319633bf73517770714\"));\n+\t\ttree.addFile(\"a=d\").setId(new ObjectId(\"fa6414df3da87840700e9eeb7fc261dd77ccd5c2\"));\n+\n+\t\tTree tree3 = (Tree) tree.findTreeMember(\"a/b.b\");\n+\t\ttree3.setId(new ObjectWriter(db).writeTree(tree3));\n+\t\tTree tree2 = (Tree) tree.findTreeMember(\"a\");\n+\t\ttree2.setId(new ObjectWriter(db).writeTree(tree2));\n+\t\ttree.setId(new ObjectWriter(db).writeTree(tree));\n+\n+\t\tIndexDiff diff = new IndexDiff(tree, index);\n+\t\tdiff.diff();\n+\t\tassertEquals(0, diff.getChanged().size());\n+\t\tassertEquals(0, diff.getAdded().size());\n+\t\tassertEquals(0, diff.getRemoved().size());\n+\t\tassertEquals(0, diff.getMissing().size());\n+\t\tassertEquals(0, diff.getModified().size());\n+\t}\n }\n-- \n1.5.4.2\n"},{"id":"69748","messageId":"1203810643-28819-4-git-send-email-robin.rosenberg@dewire.com","threadId":"12279","inReplyTo":"1203810643-28819-3-git-send-email-robin.rosenberg@dewire.com","subject":"[EGIT PATCH 03/10] WorkdirCheckout: more test for names that are close","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg@dewire.com","sentAt":"2008-02-23T23:50:36Z","receivedAt":"2008-02-23T23:50:36Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>\n---\n .../tst/org/spearce/jgit/lib/ReadTreeTest.java     |   16 +++++++++++++++-\n 1 files changed, 15 insertions(+), 1 deletions(-)\n\ndiff --git a/org.spearce.jgit.test/tst/org/spearce/jgit/lib/ReadTreeTest.java b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/ReadTreeTest.java\nindex 7ac48c9..6faedc7 100644\n--- a/org.spearce.jgit.test/tst/org/spearce/jgit/lib/ReadTreeTest.java\n+++ b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/ReadTreeTest.java\n@@ -477,7 +477,21 @@ public class ReadTreeTest extends RepositoryTestCase {\n \t\t\n \t\tassertNoConflicts();\n \t}\n-\t\n+\n+\tpublic void testCloseNameConflictsX0() throws IOException {\n+\t\tsetupCase(mkmap(\"a/a\", \"a/a-c\"), mkmap(\"a/a\",\"a/a\", \"b.b/b.b\",\"b.b/b.bs\"), mkmap(\"a/a\", \"a/a-c\") );\n+\t\tcheckout();\n+\t\tgo();\n+\t\tassertNoConflicts();\n+\t}\n+\n+\tpublic void testCloseNameConflicts1() throws IOException {\n+\t\tsetupCase(mkmap(\"a/a\", \"a/a-c\"), mkmap(\"a/a\",\"a/a\", \"a.a/a.a\",\"a.a/a.a\"), mkmap(\"a/a\", \"a/a-c\") );\n+\t\tcheckout();\n+\t\tgo();\n+\t\tassertNoConflicts();\n+\t}\n+\n \tprivate void checkout() throws IOException {\n \t\treadTree = new WorkDirCheckout(db, trash, head, index, merge);\n \t\treadTree.checkout();\n-- \n1.5.4.2\n"},{"id":"69751","messageId":"1203810643-28819-5-git-send-email-robin.rosenberg@dewire.com","threadId":"12279","inReplyTo":"1203810643-28819-4-git-send-email-robin.rosenberg@dewire.com","subject":"[EGIT PATCH 04/10] Split a big test in ReadTreeTest into smaller tests","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg@dewire.com","sentAt":"2008-02-23T23:50:37Z","receivedAt":"2008-02-23T23:50:37Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>\n---\n .../tst/org/spearce/jgit/lib/ReadTreeTest.java     |   84 +++++++++++++------\n 1 files changed, 57 insertions(+), 27 deletions(-)\n\ndiff --git a/org.spearce.jgit.test/tst/org/spearce/jgit/lib/ReadTreeTest.java b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/ReadTreeTest.java\nindex 6faedc7..70c1396 100644\n--- a/org.spearce.jgit.test/tst/org/spearce/jgit/lib/ReadTreeTest.java\n+++ b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/ReadTreeTest.java\n@@ -273,50 +273,55 @@ public class ReadTreeTest extends RepositoryTestCase {\n \t *19   D\t    0       F\t\t\t\t\t\t\t\t\t\t\t  Update\n \t */\n \t\n-\tpublic void testDirectoryFileConflicts() throws Exception {\n+\tpublic void testDirectoryFileConflicts_1() throws Exception {\n \t\t// 1\n \t\tdoit(mk(\"DF/DF\"), mk(\"DF\"), mk(\"DF/DF\"));\n \t\tassertNoConflicts();\n \t\tassertUpdated(\"DF\");\n \t\tassertRemoved(\"DF/DF\");\n-\t\t\n+\t}\n+\n+\tpublic void testDirectoryFileConflicts_2() throws Exception {\n \t\t// 2\n \t\tsetupCase(mk(\"DF/DF\"), mk(\"DF\"), mk(\"DF/DF\"));\n \t\twriteTrashFile(\"DF/DF\", \"different\");\n \t\tgo();\n \t\tassertConflict(\"DF/DF\");\n \t\t\n+\t}\n+\n+\tpublic void testDirectoryFileConflicts_3() throws Exception {\n \t\t// 3 - the first to break!\n-\t\ttearDown();\n-\t\tsetUp();\n \t\tdoit(mk(\"DF/DF\"), mk(\"DF/DF\"), mk(\"DF\"));\n \t\tassertUpdated(\"DF/DF\");\n \t\tassertRemoved(\"DF\");\n-\t\t\n+\t}\n+\n+\tpublic void testDirectoryFileConflicts_4() throws Exception {\n \t\t// 4 (basically same as 3, just with H and M different)\n-\t\ttearDown();\n-\t\tsetUp();\n \t\tdoit(mk(\"DF/DF\"), mkmap(\"DF/DF\", \"foo\"), mk(\"DF\"));\n \t\tassertUpdated(\"DF/DF\");\n \t\tassertRemoved(\"DF\");\n \t\t\n+\t}\n+\n+\tpublic void testDirectoryFileConflicts_5() throws Exception {\n \t\t// 5\n-\t\ttearDown();\n-\t\tsetUp();\n \t\tdoit(mk(\"DF/DF\"), mk(\"DF\"), mk(\"DF\"));\n \t\tassertRemoved(\"DF/DF\");\n \t\t\n+\t}\n+\n+\tpublic void testDirectoryFileConflicts_6() throws Exception {\n \t\t// 6\n-\t\ttearDown();\n-\t\tsetUp();\n \t\tsetupCase(mk(\"DF/DF\"), mk(\"DF\"), mk(\"DF\"));\n \t\twriteTrashFile(\"DF\", \"different\");\n \t\tgo();\n \t\tassertRemoved(\"DF/DF\");\n-\t\t\n+\t}\n+\n+\tpublic void testDirectoryFileConflicts_7() throws Exception {\n \t\t// 7\n-\t\ttearDown();\n-\t\tsetUp();\n \t\tdoit(mk(\"DF\"), mk(\"DF\"), mk(\"DF/DF\"));\n \t\tassertUpdated(\"DF\");\n \t\tassertRemoved(\"DF/DF\");\n@@ -334,29 +339,40 @@ public class ReadTreeTest extends RepositoryTestCase {\n \t\tassertConflict(\"DF/DF/DF/DF/DF\");\n \t\tassertUpdated(\"DF/DF\");\n \n+\t}\n+\n+\t// 8 ?\n+\n+\tpublic void testDirectoryFileConflicts_9() throws Exception {\n \t\t// 9\n-\t\ttearDown();\n-\t\tsetUp();\n \t\tdoit(mk(\"DF\"), mkmap(\"DF\", \"QP\"), mk(\"DF/DF\"));\n \t\tassertRemoved(\"DF/DF\");\n \t\tassertUpdated(\"DF\");\n-\t\t\n+\t}\n+\n+\tpublic void testDirectoryFileConflicts_10() throws Exception {\n \t\t// 10\n \t\tcleanUpDF();\n \t\tdoit(mk(\"DF\"), mk(\"DF/DF\"), mk(\"DF/DF\"));\n \t\tassertNoConflicts();\n \t\t\n+\t}\n+\n+\tpublic void testDirectoryFileConflicts_11() throws Exception {\n \t\t// 11\n-\t\tcleanUpDF();\n \t\tdoit(mk(\"DF\"), mk(\"DF/DF\"), mkmap(\"DF/DF\", \"asdf\"));\n \t\tassertConflict(\"DF/DF\");\n-\t\t\n+\t}\n+\n+\tpublic void testDirectoryFileConflicts_12() throws Exception {\n \t\t// 12\n \t\tcleanUpDF();\n \t\tdoit(mk(\"DF\"), mk(\"DF/DF\"), mk(\"DF\"));\n \t\tassertRemoved(\"DF\");\n \t\tassertUpdated(\"DF/DF\");\n-\t\t\n+\t}\n+\n+\tpublic void testDirectoryFileConflicts_13() throws Exception {\n \t\t// 13\n \t\tcleanUpDF();\n \t\tsetupCase(mk(\"DF\"), mk(\"DF/DF\"), mk(\"DF\"));\n@@ -364,29 +380,39 @@ public class ReadTreeTest extends RepositoryTestCase {\n \t\tgo();\n \t\tassertConflict(\"DF\");\n \t\tassertUpdated(\"DF/DF\");\n-\t\t\n+\t}\n+\n+\tpublic void testDirectoryFileConflicts_14() throws Exception {\n \t\t// 14\n \t\tcleanUpDF();\n \t\tdoit(mk(\"DF\"), mk(\"DF/DF\"), mkmap(\"DF\", \"Foo\"));\n \t\tassertConflict(\"DF\");\n \t\tassertUpdated(\"DF/DF\");\n-\t\t\n+\t}\n+\n+\tpublic void testDirectoryFileConflicts_15() throws Exception {\n \t\t// 15\n \t\tdoit(mkmap(), mk(\"DF/DF\"), mk(\"DF\"));\n \t\tassertRemoved(\"DF\");\n \t\tassertUpdated(\"DF/DF\");\n-\t\t\n+\t}\n+\n+\tpublic void testDirectoryFileConflicts_15b() throws Exception {\n \t\t// 15, take 2, just to check multi-leveled\n \t\tdoit(mkmap(), mk(\"DF/DF/DF/DF\"), mk(\"DF\"));\n \t\tassertRemoved(\"DF\");\n \t\tassertUpdated(\"DF/DF/DF/DF\");\n-\t\t\n+\t}\n+\n+\tpublic void testDirectoryFileConflicts_16() throws Exception {\n \t\t// 16\n \t\tcleanUpDF();\n \t\tdoit(mkmap(), mk(\"DF\"), mk(\"DF/DF/DF\"));\n \t\tassertRemoved(\"DF/DF/DF\");\n \t\tassertUpdated(\"DF\");\n-\t\t\n+\t}\n+\n+\tpublic void testDirectoryFileConflicts_17() throws Exception {\n \t\t// 17\n \t\tcleanUpDF();\n \t\tsetupCase(mkmap(), mk(\"DF\"), mk(\"DF/DF/DF\"));\n@@ -394,13 +420,17 @@ public class ReadTreeTest extends RepositoryTestCase {\n \t\tgo();\n \t\tassertConflict(\"DF/DF/DF\");\n \t\tassertUpdated(\"DF\");\n-\t\t\n+\t}\n+\n+\tpublic void testDirectoryFileConflicts_18() throws Exception {\n \t\t// 18\n \t\tcleanUpDF();\n \t\tdoit(mk(\"DF/DF\"), mk(\"DF/DF/DF/DF\"), null);\n \t\tassertRemoved(\"DF/DF\");\n \t\tassertUpdated(\"DF/DF/DF/DF\");\n-\t\t\n+\t}\n+\n+\tpublic void testDirectoryFileConflicts_19() throws Exception {\n \t\t// 19\n \t\tcleanUpDF();\n \t\tdoit(mk(\"DF/DF/DF/DF\"), mk(\"DF/DF/DF\"), null);\n-- \n1.5.4.2\n"},{"id":"69747","messageId":"1203810643-28819-6-git-send-email-robin.rosenberg@dewire.com","threadId":"12279","inReplyTo":"1203810643-28819-5-git-send-email-robin.rosenberg@dewire.com","subject":"[EGIT PATCH 05/10] Fix git sort order compare bug","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg@dewire.com","sentAt":"2008-02-23T23:50:38Z","receivedAt":"2008-02-23T23:50:38Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>\n---\n .../tst/org/spearce/jgit/lib/T0002_Tree.java       |   44 ++++++++++++++++++++\n .../src/org/spearce/jgit/lib/Tree.java             |   10 ++++-\n 2 files changed, 52 insertions(+), 2 deletions(-)\n\ndiff --git a/org.spearce.jgit.test/tst/org/spearce/jgit/lib/T0002_Tree.java b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/T0002_Tree.java\nindex 24b368f..7c7f6c0 100644\n--- a/org.spearce.jgit.test/tst/org/spearce/jgit/lib/T0002_Tree.java\n+++ b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/T0002_Tree.java\n@@ -17,6 +17,7 @@\n package org.spearce.jgit.lib;\n \n import java.io.IOException;\n+import java.io.UnsupportedEncodingException;\n import java.util.ArrayList;\n import java.util.List;\n \n@@ -24,6 +25,49 @@ public class T0002_Tree extends RepositoryTestCase {\n \tprivate static final ObjectId SOME_FAKE_ID = new ObjectId(\n \t\t\t\"0123456789abcdef0123456789abcdef01234567\");\n \n+\tprivate int compareNamesUsingSpecialCompare(String a,String b) throws UnsupportedEncodingException {\n+\t\tchar lasta = '\\0';\n+\t\tbyte[] abytes;\n+\t\tif (a.length() > 0 && a.charAt(a.length()-1) == '/') {\n+\t\t\tlasta = '/';\n+\t\t\ta = a.substring(0, a.length() - 1);\n+\t\t}\n+\t\tabytes = a.getBytes(\"ISO-8859-1\");\n+\t\tchar lastb = '\\0';\n+\t\tbyte[] bbytes;\n+\t\tif (b.length() > 0 && b.charAt(b.length()-1) == '/') {\n+\t\t\tlastb = '/';\n+\t\t\tb = b.substring(0, b.length() - 1);\n+\t\t}\n+\t\tbbytes = b.getBytes(\"ISO-8859-1\");\n+\t\treturn Tree.compareNames(abytes, bbytes, lasta, lastb);\n+\t}\n+\n+\tpublic void test000_sort_01() throws UnsupportedEncodingException {\n+\t\tassertEquals(0, compareNamesUsingSpecialCompare(\"a\",\"a\"));\n+\t}\n+\tpublic void test000_sort_02() throws UnsupportedEncodingException {\n+\t\tassertEquals(-1, compareNamesUsingSpecialCompare(\"a\",\"b\"));\n+\t\tassertEquals(1, compareNamesUsingSpecialCompare(\"b\",\"a\"));\n+\t}\n+\tpublic void test000_sort_03() throws UnsupportedEncodingException {\n+\t\tassertEquals(1, compareNamesUsingSpecialCompare(\"a:\",\"a\"));\n+\t\tassertEquals(1, compareNamesUsingSpecialCompare(\"a/\",\"a\"));\n+\t\tassertEquals(-1, compareNamesUsingSpecialCompare(\"a\",\"a/\"));\n+\t\tassertEquals(-1, compareNamesUsingSpecialCompare(\"a\",\"a:\"));\n+\t\tassertEquals(1, compareNamesUsingSpecialCompare(\"a:\",\"a/\"));\n+\t\tassertEquals(-1, compareNamesUsingSpecialCompare(\"a/\",\"a:\"));\n+\t}\n+\tpublic void test000_sort_04() throws UnsupportedEncodingException {\n+\t\tassertEquals(-1, compareNamesUsingSpecialCompare(\"a.a\",\"a/a\"));\n+\t\tassertEquals(1, compareNamesUsingSpecialCompare(\"a/a\",\"a.a\"));\n+\t}\n+\tpublic void test000_sort_05() throws UnsupportedEncodingException {\n+\t\tassertEquals(-1, compareNamesUsingSpecialCompare(\"a.\",\"a/\"));\n+\t\tassertEquals(1, compareNamesUsingSpecialCompare(\"a/\",\"a.\"));\n+\n+\t}\n+\n \tpublic void test001_createEmpty() throws IOException {\n \t\tfinal Tree t = new Tree(db);\n \t\tassertTrue(\"isLoaded\", t.isLoaded());\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Tree.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Tree.java\nindex ab83917..5d8e0e0 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/Tree.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Tree.java\n@@ -65,7 +65,10 @@ public class Tree extends TreeEntry implements Treeish {\n \t\t\telse if (aj > lastb)\n \t\t\t\treturn 1;\n \t\t\telse\n-\t\t\t\treturn 0;\n+\t\t\t\tif (j == a.length - 1)\n+\t\t\t\t\treturn 0;\n+\t\t\t\telse\n+\t\t\t\t\treturn -1;\n \t\t}\n \t\tif (k < nameEnd) {\n \t\t\tint bk = nameUTF8[k] & 0xff;\n@@ -74,7 +77,10 @@ public class Tree extends TreeEntry implements Treeish {\n \t\t\telse if (lasta > bk)\n \t\t\t\treturn 1;\n \t\t\telse\n-\t\t\t\treturn 0;\n+\t\t\t\tif (k == nameEnd - 1)\n+\t\t\t\t\treturn 0;\n+\t\t\t\telse\n+\t\t\t\t\treturn 1;\n \t\t}\n \t\tif (lasta < lastb)\n \t\t\treturn -1;\n-- \n1.5.4.2\n"},{"id":"69746","messageId":"1203810643-28819-7-git-send-email-robin.rosenberg@dewire.com","threadId":"12279","inReplyTo":"1203810643-28819-6-git-send-email-robin.rosenberg@dewire.com","subject":"[EGIT PATCH 06/10] Use the proper comparison algorithm","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg@dewire.com","sentAt":"2008-02-23T23:50:39Z","receivedAt":"2008-02-23T23:50:39Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"We must walk in Git sort order.\n\nSigned-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>\n---\n .../src/org/spearce/jgit/lib/IndexTreeWalker.java  |   31 +------------------\n 1 files changed, 2 insertions(+), 29 deletions(-)\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/IndexTreeWalker.java b/org.spearce.jgit/src/org/spearce/jgit/lib/IndexTreeWalker.java\nindex 93d5bb2..c17cea1 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/IndexTreeWalker.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/IndexTreeWalker.java\n@@ -288,38 +288,11 @@ public class IndexTreeWalker {\n \t}\n \n \tstatic int compare(TreeEntry t, Entry i) {\n-\t\tif (t.getFullName().equals(i.getName())) {\n-\t\t\tif (t instanceof Tree)\n-\t\t\t\treturn 1;\n-\t\t\treturn 0;\n-\t\t}\n-\t\treturn t.getFullName().compareTo(i.getName());\n+\t\treturn Tree.compareNames(t.getFullNameUTF8(), i.getNameUTF8(), TreeEntry.lastChar(t), TreeEntry.lastChar(i)); \n \t}\n \t\n \tstatic int compare(TreeEntry t1, TreeEntry t2) {\n-\t\tif (t1.getName().equals(t2.getName())) {\n-\t\t\tif (t1 instanceof Tree && t2 instanceof Tree)\n-\t\t\t\treturn 0;\n-\t\t\tif (t1 instanceof Tree)\n-\t\t\t\treturn 1;\n-\t\t\tif (t2 instanceof Tree)\n-\t\t\t\treturn -1;\n-\t\t\treturn 0;\n-\t\t}\n-\t\treturn t1.getName().compareTo(t2.getName());\n+\t\treturn Tree.compareNames(t1.getNameUTF8(), t2.getNameUTF8(), TreeEntry.lastChar(t1), TreeEntry.lastChar(t2)); \n \t}\n \t\n-\tstatic int compare(byte[] name1, byte[] name2) {\n-\t\tfor (int i = 0; i < name1.length && i < name2.length; i++) {\n-\t\t\tif (name1[i] < name2[i])\n-\t\t\t\treturn -1;\n-\t\t\tif (name1[i] > name2[i])\n-\t\t\t\treturn 1;\n-\t\t}\n-\t\tif (name1.length < name2.length)\n-\t\t\treturn -1;\n-\t\tif (name2.length < name1.length)\n-\t\t\treturn 1;\n-\t\treturn 0;\n-\t}\n }\n-- \n1.5.4.2\n"},{"id":"69744","messageId":"1203810643-28819-8-git-send-email-robin.rosenberg@dewire.com","threadId":"12279","inReplyTo":"1203810643-28819-7-git-send-email-robin.rosenberg@dewire.com","subject":"[EGIT PATCH 07/10] GitIndex: Get access to raw name and file mode","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg@dewire.com","sentAt":"2008-02-23T23:50:40Z","receivedAt":"2008-02-23T23:50:40Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>\n---\n .../src/org/spearce/jgit/lib/GitIndex.java         |   15 +++++++++++++++\n 1 files changed, 15 insertions(+), 0 deletions(-)\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/GitIndex.java b/org.spearce.jgit/src/org/spearce/jgit/lib/GitIndex.java\nindex 69ed270..d73866a 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/GitIndex.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/GitIndex.java\n@@ -598,6 +598,13 @@ public class GitIndex {\n \t\t}\n \n \t\t/**\n+\t\t * @return path name for this entry as byte array, hopefully UTF-8 encoded\n+\t\t */\n+\t\tpublic byte[] getNameUTF8() {\n+\t\t\treturn name;\n+\t\t}\n+\n+\t\t/**\n \t\t * @return SHA-1 of the entry managed by this index\n \t\t */\n \t\tpublic ObjectId getObjectId() {\n@@ -655,6 +662,14 @@ public class GitIndex {\n \t\t\telse\n \t\t\t\tflags &= ~0x4000;\n \t\t}\n+\n+\t\t/**\n+\t\t * Return raw file mode bits. See {@link FileMode}\n+\t\t * @return file mode bits\n+\t\t */\n+\t\tpublic int getModeBits() {\n+\t\t\treturn mode;\n+\t\t}\n \t}\n \n \tstatic class Header {\n-- \n1.5.4.2\n"},{"id":"69745","messageId":"1203810643-28819-9-git-send-email-robin.rosenberg@dewire.com","threadId":"12279","inReplyTo":"1203810643-28819-8-git-send-email-robin.rosenberg@dewire.com","subject":"[EGIT PATCH 08/10] TreeEntry: Accessors for full raw name and mode bits","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg@dewire.com","sentAt":"2008-02-23T23:50:41Z","receivedAt":"2008-02-23T23:50:41Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>\n---\n .../src/org/spearce/jgit/lib/TreeEntry.java        |   23 ++++++++++++++++++++\n 1 files changed, 23 insertions(+), 0 deletions(-)\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/TreeEntry.java b/org.spearce.jgit/src/org/spearce/jgit/lib/TreeEntry.java\nindex 8d46230..e73f5d5 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/TreeEntry.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/TreeEntry.java\n@@ -19,6 +19,8 @@ package org.spearce.jgit.lib;\n import java.io.IOException;\n import java.io.UnsupportedEncodingException;\n \n+import org.spearce.jgit.lib.GitIndex.Entry;\n+\n /**\n  * This class represents an entry in a tree, like a blob or another tree.\n  */\n@@ -189,6 +191,14 @@ public abstract class TreeEntry implements Comparable {\n \t\treturn r.toString();\n \t}\n \n+\t/**\n+\t * @return repository relative name of the entry\n+\t * FIXME better encoding\n+\t */\n+\tpublic byte[] getFullNameUTF8() {\n+\t\treturn getFullName().getBytes();\n+\t}\n+\n \tpublic int compareTo(final Object o) {\n \t\tif (this == o)\n \t\t\treturn 0;\n@@ -211,6 +221,19 @@ public abstract class TreeEntry implements Comparable {\n \t}\n \n \t/**\n+\t * Helper for accessing tree/blob/index methods.\n+\t *\n+\t * @param i\n+\t * @return '/' for Tre entries and NUL for non-treeish objects\n+\t */\n+\tfinal public static int lastChar(Entry i) {\n+\t\t// FIXME, gitlink etc. Currently Trees cannot appear in the\n+\t\t// index so '\\0' is always returned, except maybe for submodules\n+\t\t// which we do not support yet.\n+\t\treturn FileMode.TREE.equals(i.getModeBits()) ? '/' : '\\0';\n+\t}\n+\n+\t/**\n \t * See @{link {@link #accept(TreeVisitor, int)}.\n \t *\n \t * @param tv\n-- \n1.5.4.2\n"},{"id":"69750","messageId":"1203810643-28819-10-git-send-email-robin.rosenberg@dewire.com","threadId":"12279","inReplyTo":"1203810643-28819-9-git-send-email-robin.rosenberg@dewire.com","subject":"[EGIT PATCH 09/10] Implement a Tree iterator","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg@dewire.com","sentAt":"2008-02-23T23:50:42Z","receivedAt":"2008-02-23T23:50:42Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"This is an implementation of the Iterator interace. It can\nbe used for iterating over all entries in a tree in Git\norder. Since it is an iterator it can be used to walk more\nthan one tree in parallel.\n\nAlthough only post order is needed, preorder and leaves-only\nmode is also implemented here.\n\nSigned-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>\n---\n .../spearce/jgit/lib/TreeIteratorLeafOnlyTest.java |   85 +++++++++\n .../jgit/lib/TreeIteratorPostOrderTest.java        |  103 +++++++++++\n .../spearce/jgit/lib/TreeIteratorPreOrderTest.java |  103 +++++++++++\n .../src/org/spearce/jgit/lib/TreeIterator.java     |  182 ++++++++++++++++++++\n 4 files changed, 473 insertions(+), 0 deletions(-)\n create mode 100644 org.spearce.jgit.test/tst/org/spearce/jgit/lib/TreeIteratorLeafOnlyTest.java\n create mode 100644 org.spearce.jgit.test/tst/org/spearce/jgit/lib/TreeIteratorPostOrderTest.java\n create mode 100644 org.spearce.jgit.test/tst/org/spearce/jgit/lib/TreeIteratorPreOrderTest.java\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/TreeIterator.java\n\ndiff --git a/org.spearce.jgit.test/tst/org/spearce/jgit/lib/TreeIteratorLeafOnlyTest.java b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/TreeIteratorLeafOnlyTest.java\nnew file mode 100644\nindex 0000000..7d65982\n--- /dev/null\n+++ b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/TreeIteratorLeafOnlyTest.java\n@@ -0,0 +1,85 @@\n+package org.spearce.jgit.lib;\n+\n+import java.io.IOException;\n+\n+public class TreeIteratorLeafOnlyTest extends RepositoryTestCase {\n+\n+\t/** Empty tree */\n+\tpublic void testEmpty() {\n+\t\tTree tree = new Tree(db);\n+\t\tTreeIterator i = makeIterator(tree);\n+\t\tassertFalse(i.hasNext());\n+\t}\n+\n+\t/**\n+\t * one file\n+\t * \n+\t * @throws IOException\n+\t */\n+\tpublic void testSimpleF1() throws IOException {\n+\t\tTree tree = new Tree(db);\n+\t\ttree.addFile(\"x\");\n+\t\tTreeIterator i = makeIterator(tree);\n+\t\tassertTrue(i.hasNext());\n+\t\tassertEquals(\"x\", i.next().getName());\n+\t}\n+\n+\t/**\n+\t * two files\n+\t * \n+\t * @throws IOException\n+\t */\n+\tpublic void testSimpleF2() throws IOException {\n+\t\tTree tree = new Tree(db);\n+\t\ttree.addFile(\"a\");\n+\t\ttree.addFile(\"x\");\n+\t\tTreeIterator i = makeIterator(tree);\n+\t\tassertTrue(i.hasNext());\n+\t\tassertEquals(\"a\", i.next().getName());\n+\t\tassertEquals(\"x\", i.next().getName());\n+\t}\n+\n+\t/**\n+\t * Empty tree\n+\t * \n+\t * @throws IOException\n+\t */\n+\tpublic void testSimpleT() throws IOException {\n+\t\tTree tree = new Tree(db);\n+\t\ttree.addTree(\"a\");\n+\t\tTreeIterator i = makeIterator(tree);\n+\t\tassertFalse(i.hasNext());\n+\t}\n+\t\n+\tpublic void testTricky() throws IOException {\n+\t\tTree tree = new Tree(db);\n+\t\ttree.addFile(\"a.b\");\n+\t\ttree.addFile(\"a.c\");\n+\t\ttree.addFile(\"a/b.b/b\");\n+\t\ttree.addFile(\"a/b\");\n+\t\ttree.addFile(\"a/c\");\n+\t\ttree.addFile(\"a=c\");\n+\t\ttree.addFile(\"a=d\");\n+\n+\t\tTreeIterator i = makeIterator(tree);\n+\t\tassertTrue(i.hasNext());\n+\t\tassertEquals(\"a.b\", i.next().getFullName());\n+\t\tassertTrue(i.hasNext());\n+\t\tassertEquals(\"a.c\", i.next().getFullName());\n+\t\tassertTrue(i.hasNext());\n+\t\tassertEquals(\"a/b\", i.next().getFullName());\n+\t\tassertTrue(i.hasNext());\n+\t\tassertEquals(\"a/b.b/b\", i.next().getFullName());\n+\t\tassertTrue(i.hasNext());\n+\t\tassertEquals(\"a/c\", i.next().getFullName());\n+\t\tassertTrue(i.hasNext());\n+\t\tassertEquals(\"a=c\", i.next().getFullName());\n+\t\tassertTrue(i.hasNext());\n+\t\tassertEquals(\"a=d\", i.next().getFullName());\n+\t\tassertFalse(i.hasNext());\n+\t}\n+\n+\tprivate TreeIterator makeIterator(Tree tree) {\n+\t\treturn new TreeIterator(tree);\n+\t}\n+}\ndiff --git a/org.spearce.jgit.test/tst/org/spearce/jgit/lib/TreeIteratorPostOrderTest.java b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/TreeIteratorPostOrderTest.java\nnew file mode 100644\nindex 0000000..a6def1d\n--- /dev/null\n+++ b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/TreeIteratorPostOrderTest.java\n@@ -0,0 +1,103 @@\n+package org.spearce.jgit.lib;\n+\n+import java.io.IOException;\n+\n+public class TreeIteratorPostOrderTest extends RepositoryTestCase {\n+\n+\t/** Empty tree */\n+\tpublic void testEmpty() {\n+\t\tTree tree = new Tree(db);\n+\t\tTreeIterator i = makeIterator(tree);\n+\t\tassertTrue(i.hasNext());\n+\t\tassertEquals(\"\", i.next().getFullName());\n+\t\tassertFalse(i.hasNext());\n+\t}\n+\n+\t/**\n+\t * one file\n+\t * \n+\t * @throws IOException\n+\t */\n+\tpublic void testSimpleF1() throws IOException {\n+\t\tTree tree = new Tree(db);\n+\t\ttree.addFile(\"x\");\n+\t\tTreeIterator i = makeIterator(tree);\n+\t\tassertTrue(i.hasNext());\n+\t\tassertEquals(\"x\", i.next().getName());\n+\t\tassertTrue(i.hasNext());\n+\t\tassertEquals(\"\", i.next().getFullName());\n+\t\tassertFalse(i.hasNext());\n+\t}\n+\n+\t/**\n+\t * two files\n+\t * \n+\t * @throws IOException\n+\t */\n+\tpublic void testSimpleF2() throws IOException {\n+\t\tTree tree = new Tree(db);\n+\t\ttree.addFile(\"a\");\n+\t\ttree.addFile(\"x\");\n+\t\tTreeIterator i = makeIterator(tree);\n+\t\tassertTrue(i.hasNext());\n+\t\tassertEquals(\"a\", i.next().getName());\n+\t\tassertEquals(\"x\", i.next().getName());\n+\t\tassertTrue(i.hasNext());\n+\t\tassertEquals(\"\", i.next().getFullName());\n+\t\tassertFalse(i.hasNext());\n+\t}\n+\n+\t/**\n+\t * Empty tree\n+\t * \n+\t * @throws IOException\n+\t */\n+\tpublic void testSimpleT() throws IOException {\n+\t\tTree tree = new Tree(db);\n+\t\ttree.addTree(\"a\");\n+\t\tTreeIterator i = makeIterator(tree);\n+\t\tassertTrue(i.hasNext());\n+\t\tassertEquals(\"a\", i.next().getFullName());\n+\t\tassertTrue(i.hasNext());\n+\t\tassertEquals(\"\", i.next().getFullName());\n+\t\tassertFalse(i.hasNext());\n+\t}\n+\t\n+\tpublic void testTricky() throws IOException {\n+\t\tTree tree = new Tree(db);\n+\t\ttree.addFile(\"a.b\");\n+\t\ttree.addFile(\"a.c\");\n+\t\ttree.addFile(\"a/b.b/b\");\n+\t\ttree.addFile(\"a/b\");\n+\t\ttree.addFile(\"a/c\");\n+\t\ttree.addFile(\"a=c\");\n+\t\ttree.addFile(\"a=d\");\n+\n+\t\tTreeIterator i = makeIterator(tree);\n+\t\tassertTrue(i.hasNext());\n+\t\tassertEquals(\"a.b\", i.next().getFullName());\n+\t\tassertTrue(i.hasNext());\n+\t\tassertEquals(\"a.c\", i.next().getFullName());\n+\t\tassertTrue(i.hasNext());\n+\t\tassertEquals(\"a/b\", i.next().getFullName());\n+\t\tassertTrue(i.hasNext());\n+\t\tassertEquals(\"a/b.b/b\", i.next().getFullName());\n+\t\tassertTrue(i.hasNext());\n+\t\tassertEquals(\"a/b.b\", i.next().getFullName());\n+\t\tassertTrue(i.hasNext());\n+\t\tassertEquals(\"a/c\", i.next().getFullName());\n+\t\tassertTrue(i.hasNext());\n+\t\tassertEquals(\"a\", i.next().getFullName());\n+\t\tassertTrue(i.hasNext());\n+\t\tassertEquals(\"a=c\", i.next().getFullName());\n+\t\tassertTrue(i.hasNext());\n+\t\tassertEquals(\"a=d\", i.next().getFullName());\n+\t\tassertTrue(i.hasNext());\n+\t\tassertEquals(\"\", i.next().getFullName());\n+\t\tassertFalse(i.hasNext());\n+\t}\n+\n+\tprivate TreeIterator makeIterator(Tree tree) {\n+\t\treturn new TreeIterator(tree, TreeIterator.Order.POSTORDER);\n+\t}\n+}\ndiff --git a/org.spearce.jgit.test/tst/org/spearce/jgit/lib/TreeIteratorPreOrderTest.java b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/TreeIteratorPreOrderTest.java\nnew file mode 100644\nindex 0000000..e7e9bf4\n--- /dev/null\n+++ b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/TreeIteratorPreOrderTest.java\n@@ -0,0 +1,103 @@\n+package org.spearce.jgit.lib;\n+\n+import java.io.IOException;\n+\n+public class TreeIteratorPreOrderTest extends RepositoryTestCase {\n+\n+\t/** Empty tree */\n+\tpublic void testEmpty() {\n+\t\tTree tree = new Tree(db);\n+\t\tTreeIterator i = makeIterator(tree);\n+\t\tassertTrue(i.hasNext());\n+\t\tassertEquals(\"\", i.next().getFullName());\n+\t\tassertFalse(i.hasNext());\n+\t}\n+\n+\t/**\n+\t * one file\n+\t * \n+\t * @throws IOException\n+\t */\n+\tpublic void testSimpleF1() throws IOException {\n+\t\tTree tree = new Tree(db);\n+\t\ttree.addFile(\"x\");\n+\t\tTreeIterator i = makeIterator(tree);\n+\t\tassertTrue(i.hasNext());\n+\t\tassertEquals(\"\", i.next().getFullName());\n+\t\tassertTrue(i.hasNext());\n+\t\tassertEquals(\"x\", i.next().getName());\n+\t\tassertFalse(i.hasNext());\n+\t}\n+\n+\t/**\n+\t * two files\n+\t * \n+\t * @throws IOException\n+\t */\n+\tpublic void testSimpleF2() throws IOException {\n+\t\tTree tree = new Tree(db);\n+\t\ttree.addFile(\"a\");\n+\t\ttree.addFile(\"x\");\n+\t\tTreeIterator i = makeIterator(tree);\n+\t\tassertTrue(i.hasNext());\n+\t\tassertEquals(\"\", i.next().getFullName());\n+\t\tassertTrue(i.hasNext());\n+\t\tassertEquals(\"a\", i.next().getName());\n+\t\tassertEquals(\"x\", i.next().getName());\n+\t\tassertFalse(i.hasNext());\n+\t}\n+\n+\t/**\n+\t * Empty tree\n+\t * \n+\t * @throws IOException\n+\t */\n+\tpublic void testSimpleT() throws IOException {\n+\t\tTree tree = new Tree(db);\n+\t\ttree.addTree(\"a\");\n+\t\tTreeIterator i = makeIterator(tree);\n+\t\tassertTrue(i.hasNext());\n+\t\tassertEquals(\"\", i.next().getFullName());\n+\t\tassertTrue(i.hasNext());\n+\t\tassertEquals(\"a\", i.next().getFullName());\n+\t\tassertFalse(i.hasNext());\n+\t}\n+\t\n+\tpublic void testTricky() throws IOException {\n+\t\tTree tree = new Tree(db);\n+\t\ttree.addFile(\"a.b\");\n+\t\ttree.addFile(\"a.c\");\n+\t\ttree.addFile(\"a/b.b/b\");\n+\t\ttree.addFile(\"a/b\");\n+\t\ttree.addFile(\"a/c\");\n+\t\ttree.addFile(\"a=c\");\n+\t\ttree.addFile(\"a=d\");\n+\n+\t\tTreeIterator i = makeIterator(tree);\n+\t\tassertTrue(i.hasNext());\n+\t\tassertEquals(\"\", i.next().getFullName());\n+\t\tassertTrue(i.hasNext());\n+\t\tassertEquals(\"a.b\", i.next().getFullName());\n+\t\tassertTrue(i.hasNext());\n+\t\tassertEquals(\"a.c\", i.next().getFullName());\n+\t\tassertTrue(i.hasNext());\n+\t\tassertEquals(\"a\", i.next().getFullName());\n+\t\tassertTrue(i.hasNext());\n+\t\tassertEquals(\"a/b\", i.next().getFullName());\n+\t\tassertTrue(i.hasNext());\n+\t\tassertEquals(\"a/b.b\", i.next().getFullName());\n+\t\tassertTrue(i.hasNext());\n+\t\tassertEquals(\"a/b.b/b\", i.next().getFullName());\n+\t\tassertTrue(i.hasNext());\n+\t\tassertEquals(\"a/c\", i.next().getFullName());\n+\t\tassertTrue(i.hasNext());\n+\t\tassertEquals(\"a=c\", i.next().getFullName());\n+\t\tassertTrue(i.hasNext());\n+\t\tassertEquals(\"a=d\", i.next().getFullName());\n+\t\tassertFalse(i.hasNext());\n+\t}\n+\n+\tprivate TreeIterator makeIterator(Tree tree) {\n+\t\treturn new TreeIterator(tree, TreeIterator.Order.PREORDER);\n+\t}\n+}\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/TreeIterator.java b/org.spearce.jgit/src/org/spearce/jgit/lib/TreeIterator.java\nnew file mode 100644\nindex 0000000..e45d1fc\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/TreeIterator.java\n@@ -0,0 +1,182 @@\n+/*\n+ *  Copyright (C) 2008 Robin Rosenberg\n+ *\n+ *  This library is free software; you can redistribute it and/or\n+ *  modify it under the terms of the GNU Lesser General Public\n+ *  License, version 2.1, as published by the Free Software Foundation.\n+ *\n+ *  This library is distributed in the hope that it will be useful,\n+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+ *  Lesser General Public License for more details.\n+ *\n+ *  You should have received a copy of the GNU General Public\n+ *  License along with this library; if not, write to the Free Software\n+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301\n+ */\n+\n+package org.spearce.jgit.lib;\n+\n+import java.io.IOException;\n+import java.util.Iterator;\n+\n+/**\n+ * A tree iterator iterates over a tree and all its members recursing into\n+ * subtrees according to order.\n+ *\n+ * Default is to only visit leafs. An {@link Order} value can be supplied to\n+ * make the iteration include Tree nodes as well either before or after the\n+ * child nodes have been visited.\n+ */\n+public class TreeIterator implements Iterator<TreeEntry> {\n+\n+\tprivate Tree tree;\n+\n+\tprivate int index;\n+\n+\tprivate TreeIterator sub;\n+\n+\tprivate Order order;\n+\n+\tprivate boolean visitTreeNodes;\n+\n+\tprivate boolean hasVisitedTree;\n+\n+\t/**\n+\t * Traversal order\n+\t */\n+\tpublic enum Order {\n+\t\t/**\n+\t\t * Visit node first, then leaves\n+\t\t */\n+\t\tPREORDER,\n+\n+\t\t/**\n+\t\t * Visit leaves first, then node\n+\t\t */\n+\t\tPOSTORDER\n+\t};\n+\n+\t/**\n+\t * Construct a {@link TreeIterator} for visiting all non-tree nodes.\n+\t *\n+\t * @param start\n+\t */\n+\tpublic TreeIterator(Tree start) {\n+\t\tthis(start, Order.PREORDER, false);\n+\t}\n+\n+\t/**\n+\t * Construct a {@link TreeIterator} visiting all nodes in a tree in a given\n+\t * order.\n+\t *\n+\t * @param start Root node\n+\t * @param order {@link Order}\n+\t */\n+\tpublic TreeIterator(Tree start, Order order) {\n+\t\tthis(start, order, true);\n+\t}\n+\n+\t/**\n+\t * Construct a {@link TreeIterator}\n+\t *\n+\t * @param start First node to visit\n+\t * @param order Visitation {@link Order}\n+\t * @param visitTreeNode True to include tree node\n+\t */\n+\tprivate TreeIterator(Tree start, Order order, boolean visitTreeNode) {\n+\t\tthis.tree = start;\n+\t\tthis.visitTreeNodes = visitTreeNode;\n+\t\tthis.index = -1;\n+\t\tthis.order = order;\n+\t\tif (!visitTreeNodes)\n+\t\t\tthis.hasVisitedTree = true;\n+\t\ttry {\n+\t\t\tstep();\n+\t\t} catch (IOException e) {\n+\t\t\tthrow new Error(e);\n+\t\t}\n+\t}\n+\n+\tpublic TreeEntry next() {\n+\t\ttry {\n+\t\t\tTreeEntry ret = nextTreeEntry();\n+\t\t\tstep();\n+\t\t\treturn ret;\n+\t\t} catch (IOException e) {\n+\t\t\tthrow new Error(e);\n+\t\t}\n+\t}\n+\n+\tprivate TreeEntry nextTreeEntry() throws IOException {\n+\t\tTreeEntry ret;\n+\t\tif (sub != null)\n+\t\t\tret = sub.nextTreeEntry();\n+\t\telse {\n+\t\t\tif (index < 0 && order == Order.PREORDER) {\n+\t\t\t\treturn tree;\n+\t\t\t}\n+\t\t\tif (order == Order.POSTORDER && index == tree.memberCount()) {\n+\t\t\t\treturn tree;\n+\t\t\t}\n+\t\t\tret = tree.members()[index];\n+\t\t}\n+\t\treturn ret;\n+\t}\n+\n+\tpublic boolean hasNext() {\n+\t\ttry {\n+\t\t\treturn hasNextTreeEntry();\n+\t\t} catch (IOException e) {\n+\t\t\tthrow new Error(e);\n+\t\t}\n+\t}\n+\n+\tprivate boolean hasNextTreeEntry() throws IOException {\n+\t\tif (tree == null)\n+\t\t\treturn false;\n+\t\treturn sub != null\n+\t\t\t|| index < tree.memberCount()\n+\t\t\t|| order == Order.POSTORDER && index == tree.memberCount();\n+\t}\n+\n+\tprivate boolean step() throws IOException {\n+\t\tif (tree == null)\n+\t\t\treturn false;\n+\n+\t\tif (sub != null) {\n+\t\t\tif (sub.step())\n+\t\t\t\treturn true;\n+\t\t\tsub = null;\n+\t\t}\n+\n+\t\tif (index < 0 && !hasVisitedTree && order == Order.PREORDER) {\n+\t\t\thasVisitedTree = true;\n+\t\t\treturn true;\n+\t\t}\n+\n+\t\twhile (++index < tree.memberCount()) {\n+\t\t\tTreeEntry e = tree.members()[index];\n+\t\t\tif (e instanceof Tree) {\n+\t\t\t\tsub = new TreeIterator((Tree) e, order, visitTreeNodes);\n+\t\t\t\tif (sub.hasNextTreeEntry())\n+\t\t\t\t\treturn true;\n+\t\t\t\tsub = null;\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t\treturn true;\n+\t\t}\n+\n+\t\tif (index == tree.memberCount() && !hasVisitedTree\n+\t\t\t\t&& order == Order.POSTORDER) {\n+\t\t\thasVisitedTree = true;\n+\t\t\treturn true;\n+\t\t}\n+\t\treturn false;\n+\t}\n+\n+\tpublic void remove() {\n+\t\tthrow new IllegalStateException(\n+\t\t\t\t\"TreeIterator does not suppport remove()\");\n+\t}\n+}\n-- \n1.5.4.2\n"},{"id":"69752","messageId":"1203810643-28819-11-git-send-email-robin.rosenberg@dewire.com","threadId":"12279","inReplyTo":"1203810643-28819-10-git-send-email-robin.rosenberg@dewire.com","subject":"[EGIT PATCH 10/10] Rewritten IndexTreeWalker","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg@dewire.com","sentAt":"2008-02-23T23:50:43Z","receivedAt":"2008-02-23T23:50:43Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"This one works better with git order and hopefull faster\nthough that is secondary. The IndexTreeWalker used the TreeIterator\nfor simplicity.\n\nSigned-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>\n---\n .../spearce/jgit/lib/AbstractIndexTreeVisitor.java |    2 +-\n .../src/org/spearce/jgit/lib/IndexDiff.java        |    3 +-\n .../src/org/spearce/jgit/lib/IndexTreeVisitor.java |    3 +-\n .../src/org/spearce/jgit/lib/IndexTreeWalker.java  |  276 +++++++-------------\n .../src/org/spearce/jgit/lib/WorkDirCheckout.java  |    5 +-\n 5 files changed, 105 insertions(+), 184 deletions(-)\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/AbstractIndexTreeVisitor.java b/org.spearce.jgit/src/org/spearce/jgit/lib/AbstractIndexTreeVisitor.java\nindex 6f5ede4..c8962f0 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/AbstractIndexTreeVisitor.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/AbstractIndexTreeVisitor.java\n@@ -29,7 +29,7 @@ import org.spearce.jgit.lib.GitIndex.Entry;\n  *\n  */\n public class AbstractIndexTreeVisitor implements IndexTreeVisitor {\n-\tpublic void finishVisitTree(Tree tree, Tree auxTree, int i, String curDir)\n+\tpublic void finishVisitTree(Tree tree, Tree auxTree, String curDir)\n \t\t\tthrows IOException {\n \t\t// Empty\n \t}\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/IndexDiff.java b/org.spearce.jgit/src/org/spearce/jgit/lib/IndexDiff.java\nindex 5ed22d3..45fc084 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/IndexDiff.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/IndexDiff.java\n@@ -69,7 +69,8 @@ public class IndexDiff {\n \t\t\t\t\tadded.add(indexEntry.getName());\n \t\t\t\t\tanyChanges = true;\n \t\t\t\t} else if (indexEntry == null) {\n-\t\t\t\t\tremoved.add(treeEntry.getFullName());\n+\t\t\t\t\tif (!(treeEntry instanceof Tree))\n+\t\t\t\t\t\tremoved.add(treeEntry.getFullName());\n \t\t\t\t\tanyChanges = true;\n \t\t\t\t} else {\n \t\t\t\t\tif (!treeEntry.getId().equals(indexEntry.getObjectId())) {\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/IndexTreeVisitor.java b/org.spearce.jgit/src/org/spearce/jgit/lib/IndexTreeVisitor.java\nindex 0510711..26f3a33 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/IndexTreeVisitor.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/IndexTreeVisitor.java\n@@ -58,11 +58,10 @@ public interface IndexTreeVisitor {\n \t *\n \t * @param tree\n \t * @param auxTree\n-\t * @param i\n \t * @param curDir\n \t * @throws IOException\n \t */\n-\tpublic void finishVisitTree(Tree tree, Tree auxTree, int i, String curDir) throws IOException;\n+\tpublic void finishVisitTree(Tree tree, Tree auxTree, String curDir) throws IOException;\n \n \t/**\n \t * Invoked after handling all child nodes of a tree, during two way merge.\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/IndexTreeWalker.java b/org.spearce.jgit/src/org/spearce/jgit/lib/IndexTreeWalker.java\nindex c17cea1..8323310 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/IndexTreeWalker.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/IndexTreeWalker.java\n@@ -82,189 +82,92 @@ public class IndexTreeWalker {\n \t * @throws IOException\n \t */\n \tpublic void walk() throws IOException {\n-\t\twalk(mainTree, newTree, \"/\");\n+\t\twalk(mainTree, newTree, \"\");\n \t}\n \n \tprivate void walk(Tree tree, Tree auxTree, String curDir) throws IOException {\n-\t\tTreeEntry[] treeMembers = tree == null ? new TreeEntry[0] : tree.members();\n-\t\tTreeEntry[] auxTreeMembers = auxTree == null ? new TreeEntry[0] : auxTree.members();\n-\t\tint treeCounter = 0;\n-\t\tint auxTreeCounter = 0;\n-\t\t\n+\t\tTreeIterator mi = new TreeIterator(tree, TreeIterator.Order.POSTORDER);\n+\t\tTreeIterator ai = new TreeIterator(auxTree, TreeIterator.Order.POSTORDER);\n+\t\tTreeEntry m = mi.hasNext() ? mi.next() : null;\n+\t\tTreeEntry a = ai.hasNext() ? ai.next() : null;\n \t\tint curIndexPos = indexCounter;\n-\t\t\n-\t\twhile (treeCounter < treeMembers.length || \n-\t\t\t\tindexCounter < indexMembers.length || \n-\t\t\t\tauxTreeCounter < auxTreeMembers.length) {\n-\t\t\tTreeEntry h = treeCounter < treeMembers.length ? treeMembers[treeCounter] : null;\n-\t\t\tTreeEntry m = auxTreeCounter < auxTreeMembers.length ? auxTreeMembers[auxTreeCounter] : null;\n-\t\t\tEntry i = indexCounter < indexMembers.length ? indexMembers[indexCounter] : null;\n-\n-\t\t\tString indexName = i == null ? null : i.getName();\n-\t\t\tString treeName = h == null ? null : h.getFullName();\n-\t\t\tString auxTreeName = m == null ? null : m.getFullName();\n+\t\tEntry i = indexCounter < indexMembers.length ? indexMembers[indexCounter++] : null;\n+\t\twhile (m != null || a != null || i != null) {\n+\t\t\tint cmpma = compare(m, a);\n+\t\t\tint cmpmi = compare(m, i);\n+\t\t\tint cmpai = compare(a, i);\n \t\t\t\n-\t\t\tif (treeName != null && indexName != null && auxTreeName != null) { \n-\t\t\t\tif (eq(h, i) && eq(m, i)) {\n-\t\t\t\t\t// H == I == M\n-\t\t\t\t\tvisitor.visitEntry(h, m, i, new File(root, treeName));\n-\t\t\t\t\t\n-\t\t\t\t\ttreeCounter++;\n-\t\t\t\t\tindexCounter++;\n-\t\t\t\t\tauxTreeCounter++;\n-\t\t\t\t} else if (eq(h, i) && lt(h, m)) {\n-\t\t\t\t\t// H == I, H < M\n-\t\t\t\t\tvisitor.visitEntry(h, null, i, new File(root, treeName));\n-\t\t\t\t\t\n-\t\t\t\t\ttreeCounter++;\n-\t\t\t\t\tindexCounter++;\n-\t\t\t\t} else if (eq(h, m) && lt(h, i)) {\n-\t\t\t\t\t// H == M, H < I\n-\t\t\t\t\tif (h instanceof Tree) {\n-\t\t\t\t\t\twalk((Tree)h, (Tree)m, \"/\" + treeName);\n-\t\t\t\t\t} else {\n-\t\t\t\t\t\tvisitor.visitEntry(h, m, null, new File(root, treeName));\n-\t\t\t\t\t}\n-\t\t\t\t\t\n-\t\t\t\t\ttreeCounter++;\n-\t\t\t\t\tauxTreeCounter++;\n-\t\t\t\t\t\n-\t\t\t\t\t\n-\t\t\t\t} else if (eq(m, i) && lt(i, h)) {\n-\t\t\t\t\t// I == M, I < H\n-\t\t\t\t\tvisitor.visitEntry(null, m, i, new File(root, indexName));\n-\t\t\t\t\t\n-\t\t\t\t\tindexCounter++;\n-\t\t\t\t\tauxTreeCounter++;\n-\t\t\t\t} else if (lt(h, i) && lt(h, m)) {\n-\t\t\t\t\t// H < I, H < M\n-\t\t\t\t\tif (h instanceof Tree) {\n-\t\t\t\t\t\twalk((Tree) h, null, \"/\" + treeName);\n-\t\t\t\t\t} else {\n-\t\t\t\t\t\tvisitor.visitEntry(h, null, null, new File(root, treeName));\n-\t\t\t\t\t}\n-\t\t\t\t\t\n-\t\t\t\t\ttreeCounter++;\n-\t\t\t\t} else if (lt(m, i) && lt(m, h)) {\n-\t\t\t\t\t// M < I, M < H\n-\t\t\t\t\tif (m instanceof Tree) {\n-\t\t\t\t\t\twalk(null, (Tree) m, \"/\" + auxTreeName);\n-\t\t\t\t\t} else {\n-\t\t\t\t\t\tvisitor.visitEntry(null, m, null, new File(root, auxTreeName));\n-\t\t\t\t\t}\n-\t\t\t\t\t\n-\t\t\t\t\tauxTreeCounter++;\n-\t\t\t\t} else { // index entry is first\n-\t\t\t\t\t// I < H, I < M\n-\t\t\t\t\tvisitor.visitEntry(null, null, i, new File(root, indexName));\n-\t\t\t\t\t\n-\t\t\t\t\tindexCounter++;\n-\t\t\t\t}\n-\t\t\t} else if (treeName != null && indexName != null) {\n-\t\t\t\tif (eq(h, i)) {\n-\t\t\t\t\tif (threeTrees)\n-\t\t\t\t\t\tvisitor.visitEntry(h, null, i, new File(root, indexName));\n-\t\t\t\t\telse visitor.visitEntry(h, i, new File(root, indexName));\n-\t\t\t\t\t\n-\t\t\t\t\ttreeCounter++;\n-\t\t\t\t\tindexCounter++;\n-\t\t\t\t} else if (lt(h, i)) {\n-\t\t\t\t\tif (h instanceof Tree) \n-\t\t\t\t\t\twalk((Tree) h, null, \"/\" + treeName);\n-\t\t\t\t\telse {\n-\t\t\t\t\t\tif (threeTrees) {\n-\t\t\t\t\t\t\tvisitor.visitEntry(h, null, null, new File(root, treeName));\n-\t\t\t\t\t\t} else visitor.visitEntry(h, null, new File(root, treeName));\n-\t\t\t\t\t}\n-\t\t\t\t\t\n-\t\t\t\t\ttreeCounter++;\n-\t\t\t\t} else { // lt(i, h)\n-\t\t\t\t\tif (threeTrees) {\n-\t\t\t\t\t\tvisitor.visitEntry(null, null, i, new File(root, indexName));\n-\t\t\t\t\t} else visitor.visitEntry(null, i, new File(root, indexName));\n-\t\t\t\t\t\n-\t\t\t\t\tindexCounter++;\n-\t\t\t\t}\n-\t\t\t} else if (treeName != null && auxTreeName != null) {\n-\t\t\t\tif (eq(h, m)) {\n-\t\t\t\t\tif (h instanceof Tree) {\n-\t\t\t\t\t\twalk((Tree) h, (Tree) m, \"/\" + treeName);\n-\t\t\t\t\t} else {\n-\t\t\t\t\t\tvisitor.visitEntry(h, m, null, new File(root, treeName));\n-\t\t\t\t\t}\n-\t\t\t\t\t\n-\t\t\t\t\ttreeCounter++;\n-\t\t\t\t\tauxTreeCounter++;\n-\t\t\t\t} else if (lt(h, m)) {\n-\t\t\t\t\tif (h instanceof Tree) {\n-\t\t\t\t\t\twalk((Tree) h, null, \"/\" + treeName);\n-\t\t\t\t\t} else {\n-\t\t\t\t\t\tvisitor.visitEntry(h, null, null, new File(root, treeName));\n-\t\t\t\t\t}\n-\t\t\t\t\t\n-\t\t\t\t\ttreeCounter++;\n-\t\t\t\t} else { // lt(m, h)\n-\t\t\t\t\tif (m instanceof Tree) {\n-\t\t\t\t\t\twalk(null, (Tree) m, \"/\" + auxTreeName);\n-\t\t\t\t\t} else {\n-\t\t\t\t\t\tvisitor.visitEntry(null, m, null, new File(\"/\" + auxTreeName));\n-\t\t\t\t\t}\n-\t\t\t\t\t\t\n-\t\t\t\t\tauxTreeCounter++;\n-\t\t\t\t}\n-\t\t\t\t\n-\t\t\t} else if (indexName != null && auxTreeName != null) {\n-\t\t\t\tif (eq(m, i)) {\n-\t\t\t\t\tvisitor.visitEntry(null, m, i, new File(root, indexName));\n-\t\t\t\t\t\n-\t\t\t\t\tauxTreeCounter++;\n-\t\t\t\t\tindexCounter++;\n-\t\t\t\t} else if (lt(m, i)) {\n-\t\t\t\t\tif (m instanceof Tree) \n-\t\t\t\t\t\twalk(null, (Tree) m, \"/\" + auxTreeName);\n-\t\t\t\t\telse {\n-\t\t\t\t\t\tvisitor.visitEntry(null, m, null, new File(root, auxTreeName));\n-\t\t\t\t\t}\n-\t\t\t\t\t\n-\t\t\t\t\tauxTreeCounter++;\n-\t\t\t\t} else { // lt(i, m)\n-\t\t\t\t\tvisitor.visitEntry(null, null, i, new File(root, indexName));\n-\t\t\t\t\t\n-\t\t\t\t\tindexCounter++;\n-\t\t\t\t}\n-\t\t\t} else if (treeName != null) {\n-\t\t\t\tif (h instanceof Tree) {\n-\t\t\t\t\twalk((Tree) h, null, \"/\" + treeName);\n-\t\t\t\t} else if (threeTrees)\n-\t\t\t\t\tvisitor.visitEntry(h, null, null, new File(root, treeName));\n-\t\t\t\telse visitor.visitEntry(h, null, new File(root, treeName));\n-\t\t\t\t\n-\t\t\t\ttreeCounter++;\n-\t\t\t} else if (auxTreeName != null) {\n-\t\t\t\tif (m instanceof Tree) {\n-\t\t\t\t\twalk(null, (Tree)m, \"/\" + auxTreeName);\n-\t\t\t\t} else visitor.visitEntry(null, m, null, new File(root, auxTreeName));\n-\t\t\t\t\n-\t\t\t\tauxTreeCounter++;\n-\t\t\t} else if (indexName != null) {\n-\t\t\t\t// need to check if we're done with this tree\n-\t\t\t\tString curDirNoSlash = curDir.substring(1);\n-\t\t\t\tif (!indexName.startsWith(curDirNoSlash + \"/\") && curDirNoSlash.length() != 0)\n-\t\t\t\t\tbreak;\n-\t\t\t\t\n-\t\t\t\tif (threeTrees)\n-\t\t\t\t\tvisitor.visitEntry(null, null, i, new File(root, indexName));\n-\t\t\t\telse visitor.visitEntry(null, i, new File(root, indexName));\n-\t\t\t\tindexCounter++;\n-\t\t\t}\n+\t\t\tTreeEntry pm = cmpma <= 0 && cmpmi <= 0 ? m : null;\n+\t\t\tTreeEntry pa = cmpma >= 0 && cmpai <= 0 ? a : null;\n+\t\t\tEntry     pi = cmpmi >= 0 && cmpai >= 0 ? i : null;\n+\n+\t\t\tif (pi != null)\n+\t\t\t\tvisitEntry(pm, pa, pi, root);\n+\t\t\telse\n+\t\t\t\tfinishVisitTree(pm, pa, curIndexPos, root);\n+\n+\t\t\tif (pm != null) m = mi.hasNext() ? mi.next() : null;\n+\t\t\tif (pa != null) a = ai.hasNext() ? ai.next() : null;\n+\t\t\tif (pi != null) i = indexCounter < indexMembers.length ? indexMembers[indexCounter++] : null;\n \t\t}\n-\t\t\n-\t\tif (threeTrees) {\n-\t\t\tvisitor.finishVisitTree(tree, auxTree, indexCounter - curIndexPos, \n-\t\t\t\t\tcurDir.substring(1));\n-\t\t} else {\n-\t\t\tvisitor.finishVisitTree(tree, indexCounter - curIndexPos, curDir);\n+\t}\n+\n+\tprivate void visitEntry(TreeEntry t1, TreeEntry t2,\n+\t\t\tEntry i, File root) throws IOException {\n+\n+\t\tassert t1 != null || t2 != null || i != null : \"Needs at least one entry\";\n+\t\tassert root != null : \"Needs workdir\";\n+\n+\t\tif (t1 != null && t1.getParent() == null)\n+\t\t\tt1 = null;\n+\t\tif (t2 != null && t2.getParent() == null)\n+\t\t\tt2 = null;\n+\n+\t\tFile f = null;\n+\t\tif (i != null)\n+\t\t\tf = new File(root, i.getName());\n+\t\telse if (t1 != null)\n+\t\t\tf = new File(root, t1.getFullName());\n+\t\telse if (t2 != null)\n+\t\t\tf = new File(root, t2.getFullName());\n+\n+\t\tif (t1 != null || t2 != null || i != null)\n+\t\t\tif (threeTrees)\n+\t\t\t\tvisitor.visitEntry(t1, t2, i, f);\n+\t\t\telse\n+\t\t\t\tvisitor.visitEntry(t1, i, f);\n+\t}\n+\n+\tprivate void finishVisitTree(TreeEntry t1, TreeEntry t2, int curIndexPos, File root)\n+\t\t\tthrows IOException {\n+\n+\t\tassert t1 != null || t2 != null : \"Needs at least one entry\";\n+\t\tassert root != null : \"Needs workdir\";\n+\n+\t\tif (t1 != null && t1.getParent() == null)\n+\t\t\tt1 = null;\n+\t\tif (t2 != null && t2.getParent() == null)\n+\t\t\tt2 = null;\n+\n+\t\tFile f = null;\n+\t\tString c= null;\n+\t\tif (t1 != null) {\n+\t\t\tc = t1.getFullName();\n+\t\t\tf = new File(root, c);\n+\t\t} else if (t2 != null) {\n+\t\t\tc = t2.getFullName();\n+\t\t\tf = new File(root, c);\n \t\t}\n+\t\tif (t1 instanceof Tree || t2 instanceof Tree)\n+\t\t\tif (threeTrees)\n+\t\t\t\tvisitor.finishVisitTree((Tree)t1, (Tree)t2, c);\n+\t\t\telse\n+\t\t\t\tvisitor.finishVisitTree((Tree)t1, indexCounter - curIndexPos, c);\n+\t\telse if (t1 != null || t2 != null)\n+\t\t\tif (threeTrees)\n+\t\t\t\tvisitor.visitEntry(t1, t2, null, f);\n+\t\t\telse\n+\t\t\t\tvisitor.visitEntry(t1, null, f);\n \t}\n \n \tstatic boolean lt(TreeEntry h, Entry i) {\n@@ -288,11 +191,30 @@ public class IndexTreeWalker {\n \t}\n \n \tstatic int compare(TreeEntry t, Entry i) {\n+\t\tif (t == null && i == null)\n+\t\t\treturn 0;\n+\t\tif (t == null)\n+\t\t\treturn 1;\n+\t\tif (i == null)\n+\t\t\treturn -1;\n \t\treturn Tree.compareNames(t.getFullNameUTF8(), i.getNameUTF8(), TreeEntry.lastChar(t), TreeEntry.lastChar(i)); \n \t}\n \t\n \tstatic int compare(TreeEntry t1, TreeEntry t2) {\n-\t\treturn Tree.compareNames(t1.getNameUTF8(), t2.getNameUTF8(), TreeEntry.lastChar(t1), TreeEntry.lastChar(t2)); \n+\t\tif (t1 != null && t1.getParent() == null && t2 != null && t2.getParent() == null)\n+\t\t\treturn 0;\n+\t\tif (t1 != null && t1.getParent() == null)\n+\t\t\treturn -1;\n+\t\tif (t2 != null && t2.getParent() == null)\n+\t\t\treturn 1;\n+\n+\t\tif (t1 == null && t2 == null)\n+\t\t\treturn 0;\n+\t\tif (t1 == null)\n+\t\t\treturn 1;\n+\t\tif (t2 == null)\n+\t\t\treturn -1;\n+\t\treturn Tree.compareNames(t1.getFullNameUTF8(), t2.getFullNameUTF8(), TreeEntry.lastChar(t1), TreeEntry.lastChar(t2));\n \t}\n \t\n }\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/WorkDirCheckout.java b/org.spearce.jgit/src/org/spearce/jgit/lib/WorkDirCheckout.java\nindex 04785e4..40ad332 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/WorkDirCheckout.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/WorkDirCheckout.java\n@@ -243,11 +243,10 @@ public class WorkDirCheckout {\n \t\t\t}\n \t\n \t\t\t@Override\n-\t\t\tpublic void finishVisitTree(Tree tree, Tree auxTree, int i,\n-\t\t\t\t\tString curDir) throws IOException {\n+\t\t\tpublic void finishVisitTree(Tree tree, Tree auxTree, String curDir) throws IOException {\n \t\t\t\tif (curDir.length() == 0) return;\n \t\t\t\t\n-\t\t\t\tif (auxTree != null && i == 0) {\n+\t\t\t\tif (auxTree != null) {\n \t\t\t\t\tif (index.getEntry(curDir) != null)\n \t\t\t\t\t\tremoved.add(curDir);\n \t\t\t\t} \n-- \n1.5.4.2\n"},{"id":"70784","messageId":"20080303141704.GA48263@mimvista.com","threadId":"12279","inReplyTo":"1203810643-28819-1-git-send-email-robin.rosenberg@dewire.com","subject":"Re: [EGIT] Sort order from hell fixes, take 2","fromName":"David Watson","fromEmail":"dwatson@mimvista.com","sentAt":"2008-03-03T14:17:04Z","receivedAt":"2008-03-03T14:17:04Z","isPatch":false,"sender":{"key":"dwatson@mimvista.com","avatar":null},"body":"I've looked over this a bit, and it looks like a good set of changes. \n\n\nOn Sun, Feb 24, 2008 at 12:50:33AM +0100, Robin Rosenberg wrote:\n> Hi fans,\n> \n> My previous attempt to fix this failed, so here is another round, including\n> some new infrastructure like a TreeIterator to support this fix and whatever\n> will need it.\n> \n> Feed free to scrutize and invent whatever evil test case might be missing.\n> \n> The reason I noticed the problem was introduced in c20142, where the unit\n> tests for org.spearce.jgit was moved to the new project org.spearce.jgit.test .\n> \n> -- robin\n> \n> \n\n-- \nDave Watson\nSoftware Engineer\nMIMvista Corp\n"}]}