{"thread":{"id":"13934","subject":"[JGIT PATCH v4] Implementation of fnmatch and the ignore rules","startedAt":"2008-06-13T18:30:34Z","lastAt":"2008-06-18T06:43:43Z","messageCount":26,"participants":["Florian Köberle","Florian Koeberle","Robin Rosenberg"],"isPatch":true,"patchVersion":4,"patchTotal":null},"messages":[{"id":"79748","messageId":"4852BCCA.4030404@web.de","threadId":"13934","inReplyTo":null,"subject":"[JGIT PATCH v4] Implementation of fnmatch and the ignore rules","fromName":"Florian Köberle","fromEmail":"florianskarten@web.de","sentAt":"2008-06-13T18:30:34Z","receivedAt":"2008-06-13T18:30:34Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"-----BEGIN PGP SIGNED MESSAGE-----\nHash: SHA1\n\nHi\n\nThanks for the suggestions and comments, the new patches are available here:\nhttp://repo.or.cz/w/egit/florian.git?a=shortlog;h=refs/heads/mailinglist-patches-4\n\nI will send them as a reply to this email soon.\n\n\nThe most noticeable change is that I improved the fnmatch functionality.\n\nAll character classes of the type [:class:] work now.\nOther character classes, including the character classes [=class=] and\n[.class.] will cause a InvalidPatternException. The last two aren't\nsupported at my bash neighter, but are defined in the POSIX standard.\n\nTwo other implementation differences are:\n\nThe bash shell doesn't support the full range of digits, but my\nimplementatiton does. e.g. ۹ (U+06F9 EXTENDED ARABIC-INDIC DIGIT NINE)\n\nA pattern like [[:] results in a InvalidPatternException in my\nimplementation. The shell has there a strange behavior: if the files \"[\"\nand \":\" exists then \"ls [[:]\" shows only \":\".\n\n\nThe other main change is that I introduced a AbstractTestCase class\nwhich which offers functionality to create temporary folders.\nRepositoryTestCase extends now from this new class.\n\nAn other patch reducing the duplication between AbstractTestCase and\nRepositoryTestCase class will follow soon, if you like the change.\n\n\nI also updated all license statements to the 3-clause BSD.\n\nEven if you don't like the last change (the AbstractTestCase change) it\nwould be cool if you would accept at least some patches.\n\nBest regards,\nFlorian\n-----BEGIN PGP SIGNATURE-----\nVersion: GnuPG v1.4.6 (GNU/Linux)\nComment: Using GnuPG with Mozilla - http://enigmail.mozdev.org\n\niD8DBQFIUrzK59ca4mzhfxMRAg+XAKDUoEdpil0+qqZ0pgMx/yJYKd2ztwCfe4aI\nfqJ25VXnX2RWEay9aH4Np6Y=\n=4i44\n-----END PGP SIGNATURE-----\n"},{"id":"79751","messageId":"1213382121-19786-1-git-send-email-florianskarten@web.de","threadId":"13934","inReplyTo":"4852BCCA.4030404@web.de","subject":"[JGIT PATCH v4 01/24] Added the package fnmatch and two exceptions.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-06-13T18:34:58Z","receivedAt":"2008-06-13T18:34:58Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Signed-off-by: Florian Koeberle <florianskarten@web.de>\n---\n .../spearce/jgit/fnmatch/FileNameMatcherTest.java  |  678 ++++++++++++++++++++\n .../jgit/errors/InvalidPatternException.java       |   65 ++\n .../jgit/errors/NoClosingBracketException.java     |   69 ++\n .../src/org/spearce/jgit/fnmatch/AbstractHead.java |   74 +++\n .../org/spearce/jgit/fnmatch/CharacterHead.java    |   53 ++\n .../org/spearce/jgit/fnmatch/FileNameMatcher.java  |  327 ++++++++++\n .../src/org/spearce/jgit/fnmatch/GroupHead.java    |  220 +++++++\n .../src/org/spearce/jgit/fnmatch/Head.java         |   50 ++\n .../src/org/spearce/jgit/fnmatch/LastHead.java     |   56 ++\n .../jgit/fnmatch/RestrictedWildCardHead.java       |   52 ++\n .../src/org/spearce/jgit/fnmatch/WildCardHead.java |   49 ++\n 11 files changed, 1693 insertions(+), 0 deletions(-)\n create mode 100644 org.spearce.jgit.test/tst/org/spearce/jgit/fnmatch/FileNameMatcherTest.java\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/errors/InvalidPatternException.java\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/errors/NoClosingBracketException.java\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/fnmatch/AbstractHead.java\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/fnmatch/CharacterHead.java\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/fnmatch/FileNameMatcher.java\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/fnmatch/GroupHead.java\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/fnmatch/Head.java\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/fnmatch/LastHead.java\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/fnmatch/RestrictedWildCardHead.java\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/fnmatch/WildCardHead.java\n\ndiff --git a/org.spearce.jgit.test/tst/org/spearce/jgit/fnmatch/FileNameMatcherTest.java b/org.spearce.jgit.test/tst/org/spearce/jgit/fnmatch/FileNameMatcherTest.java\nnew file mode 100644\nindex 0000000..74e88fa\n--- /dev/null\n+++ b/org.spearce.jgit.test/tst/org/spearce/jgit/fnmatch/FileNameMatcherTest.java\n@@ -0,0 +1,678 @@\n+/*\n+ * Copyright (C) 2008, Florian KÃ¶berle <florianskarten@web.de>\n+ *\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or\n+ * without modification, are permitted provided that the following\n+ * conditions are met:\n+ *\n+ * - Redistributions of source code must retain the above copyright\n+ *   notice, this list of conditions and the following disclaimer.\n+ *\n+ * - Redistributions in binary form must reproduce the above\n+ *   copyright notice, this list of conditions and the following\n+ *   disclaimer in the documentation and/or other materials provided\n+ *   with the distribution.\n+ *\n+ * - Neither the name of the Git Development Community nor the\n+ *   names of its contributors may be used to endorse or promote\n+ *   products derived from this software without specific prior\n+ *   written permission.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n+ * CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+package org.spearce.jgit.fnmatch;\n+\n+import org.spearce.jgit.errors.InvalidPatternException;\n+import org.spearce.jgit.fnmatch.FileNameMatcher;\n+\n+import junit.framework.TestCase;\n+\n+public class FileNameMatcherTest extends TestCase {\n+\n+\tprivate void assertMatch(final String pattern, final String input,\n+\t\t\tfinal boolean matchExpected, final boolean appendCanMatchExpected)\n+\t\t\tthrows InvalidPatternException {\n+\t\tfinal FileNameMatcher matcher = new FileNameMatcher(pattern, null);\n+\t\tmatcher.append(input);\n+\t\tassertEquals(matchExpected, matcher.isMatch());\n+\t\tassertEquals(appendCanMatchExpected, matcher.canAppendMatch());\n+\t}\n+\n+\tprivate void assertFileNameMatch(final String pattern, final String input,\n+\t\t\tfinal char excludedCharacter, final boolean matchExpected,\n+\t\t\tfinal boolean appendCanMatchExpected)\n+\t\t\tthrows InvalidPatternException {\n+\t\tfinal FileNameMatcher matcher = new FileNameMatcher(pattern,\n+\t\t\t\tnew Character(excludedCharacter));\n+\t\tmatcher.append(input);\n+\t\tassertEquals(matchExpected, matcher.isMatch());\n+\t\tassertEquals(appendCanMatchExpected, matcher.canAppendMatch());\n+\t}\n+\n+\tpublic void testVerySimplePatternCase0() throws Exception {\n+\t\tassertMatch(\"\", \"\", true, false);\n+\t}\n+\n+\tpublic void testVerySimplePatternCase1() throws Exception {\n+\t\tassertMatch(\"ab\", \"a\", false, true);\n+\t}\n+\n+\tpublic void testVerySimplePatternCase2() throws Exception {\n+\t\tassertMatch(\"ab\", \"ab\", true, false);\n+\t}\n+\n+\tpublic void testVerySimplePatternCase3() throws Exception {\n+\t\tassertMatch(\"ab\", \"ac\", false, false);\n+\t}\n+\n+\tpublic void testVerySimplePatternCase4() throws Exception {\n+\t\tassertMatch(\"ab\", \"abc\", false, false);\n+\t}\n+\n+\tpublic void testVerySimpleWirdcardCase0() throws Exception {\n+\t\tassertMatch(\"?\", \"a\", true, false);\n+\t}\n+\n+\tpublic void testVerySimpleWildCardCase1() throws Exception {\n+\t\tassertMatch(\"??\", \"a\", false, true);\n+\t}\n+\n+\tpublic void testVerySimpleWildCardCase2() throws Exception {\n+\t\tassertMatch(\"??\", \"ab\", true, false);\n+\t}\n+\n+\tpublic void testVerySimpleWildCardCase3() throws Exception {\n+\t\tassertMatch(\"??\", \"abc\", false, false);\n+\t}\n+\n+\tpublic void testVerySimpleStarCase0() throws Exception {\n+\t\tassertMatch(\"*\", \"\", true, true);\n+\t}\n+\n+\tpublic void testVerySimpleStarCase1() throws Exception {\n+\t\tassertMatch(\"*\", \"a\", true, true);\n+\t}\n+\n+\tpublic void testVerySimpleStarCase2() throws Exception {\n+\t\tassertMatch(\"*\", \"ab\", true, true);\n+\t}\n+\n+\tpublic void testSimpleStarCase0() throws Exception {\n+\t\tassertMatch(\"a*b\", \"a\", false, true);\n+\t}\n+\n+\tpublic void testSimpleStarCase1() throws Exception {\n+\t\tassertMatch(\"a*c\", \"ac\", true, true);\n+\t}\n+\n+\tpublic void testSimpleStarCase2() throws Exception {\n+\t\tassertMatch(\"a*c\", \"ab\", false, true);\n+\t}\n+\n+\tpublic void testSimpleStarCase3() throws Exception {\n+\t\tassertMatch(\"a*c\", \"abc\", true, true);\n+\t}\n+\n+\tpublic void testManySolutionsCase0() throws Exception {\n+\t\tassertMatch(\"a*a*a\", \"aaa\", true, true);\n+\t}\n+\n+\tpublic void testManySolutionsCase1() throws Exception {\n+\t\tassertMatch(\"a*a*a\", \"aaaa\", true, true);\n+\t}\n+\n+\tpublic void testManySolutionsCase2() throws Exception {\n+\t\tassertMatch(\"a*a*a\", \"ababa\", true, true);\n+\t}\n+\n+\tpublic void testManySolutionsCase3() throws Exception {\n+\t\tassertMatch(\"a*a*a\", \"aaaaaaaa\", true, true);\n+\t}\n+\n+\tpublic void testManySolutionsCase4() throws Exception {\n+\t\tassertMatch(\"a*a*a\", \"aaaaaaab\", false, true);\n+\t}\n+\n+\tpublic void testVerySimpleGroupCase0() throws Exception {\n+\t\tassertMatch(\"[ab]\", \"a\", true, false);\n+\t}\n+\n+\tpublic void testVerySimpleGroupCase1() throws Exception {\n+\t\tassertMatch(\"[ab]\", \"b\", true, false);\n+\t}\n+\n+\tpublic void testVerySimpleGroupCase2() throws Exception {\n+\t\tassertMatch(\"[ab]\", \"ab\", false, false);\n+\t}\n+\n+\tpublic void testVerySimpleGroupRangeCase0() throws Exception {\n+\t\tassertMatch(\"[b-d]\", \"a\", false, false);\n+\t}\n+\n+\tpublic void testVerySimpleGroupRangeCase1() throws Exception {\n+\t\tassertMatch(\"[b-d]\", \"b\", true, false);\n+\t}\n+\n+\tpublic void testVerySimpleGroupRangeCase2() throws Exception {\n+\t\tassertMatch(\"[b-d]\", \"c\", true, false);\n+\t}\n+\n+\tpublic void testVerySimpleGroupRangeCase3() throws Exception {\n+\t\tassertMatch(\"[b-d]\", \"d\", true, false);\n+\t}\n+\n+\tpublic void testVerySimpleGroupRangeCase4() throws Exception {\n+\t\tassertMatch(\"[b-d]\", \"e\", false, false);\n+\t}\n+\n+\tpublic void testVerySimpleGroupRangeCase5() throws Exception {\n+\t\tassertMatch(\"[b-d]\", \"-\", false, false);\n+\t}\n+\n+\tpublic void testTwoGroupsCase0() throws Exception {\n+\t\tassertMatch(\"[b-d][ab]\", \"bb\", true, false);\n+\t}\n+\n+\tpublic void testTwoGroupsCase1() throws Exception {\n+\t\tassertMatch(\"[b-d][ab]\", \"ca\", true, false);\n+\t}\n+\n+\tpublic void testTwoGroupsCase2() throws Exception {\n+\t\tassertMatch(\"[b-d][ab]\", \"fa\", false, false);\n+\t}\n+\n+\tpublic void testTwoGroupsCase3() throws Exception {\n+\t\tassertMatch(\"[b-d][ab]\", \"bc\", false, false);\n+\t}\n+\n+\tpublic void testTwoRangesInOneGroupCase0() throws Exception {\n+\t\tassertMatch(\"[b-ce-e]\", \"a\", false, false);\n+\t}\n+\n+\tpublic void testTwoRangesInOneGroupCase1() throws Exception {\n+\t\tassertMatch(\"[b-ce-e]\", \"b\", true, false);\n+\t}\n+\n+\tpublic void testTwoRangesInOneGroupCase2() throws Exception {\n+\t\tassertMatch(\"[b-ce-e]\", \"c\", true, false);\n+\t}\n+\n+\tpublic void testTwoRangesInOneGroupCase3() throws Exception {\n+\t\tassertMatch(\"[b-ce-e]\", \"d\", false, false);\n+\t}\n+\n+\tpublic void testTwoRangesInOneGroupCase4() throws Exception {\n+\t\tassertMatch(\"[b-ce-e]\", \"e\", true, false);\n+\t}\n+\n+\tpublic void testTwoRangesInOneGroupCase5() throws Exception {\n+\t\tassertMatch(\"[b-ce-e]\", \"f\", false, false);\n+\t}\n+\n+\tpublic void testIncompleteRangesInOneGroupCase0() throws Exception {\n+\t\tassertMatch(\"a[b-]\", \"ab\", true, false);\n+\t}\n+\n+\tpublic void testIncompleteRangesInOneGroupCase1() throws Exception {\n+\t\tassertMatch(\"a[b-]\", \"ac\", false, false);\n+\t}\n+\n+\tpublic void testIncompleteRangesInOneGroupCase2() throws Exception {\n+\t\tassertMatch(\"a[b-]\", \"a-\", true, false);\n+\t}\n+\n+\tpublic void testCombinedRangesInOneGroupCase0() throws Exception {\n+\t\tassertMatch(\"[a-c-e]\", \"b\", true, false);\n+\t}\n+\n+\t/**\n+\t * The c belongs to the range a-c. \"-e\" is no valid range so d should not\n+\t * match.\n+\t * \n+\t * @throws Exception\n+\t *             for some reasons\n+\t */\n+\tpublic void testCombinedRangesInOneGroupCase1() throws Exception {\n+\t\tassertMatch(\"[a-c-e]\", \"d\", false, false);\n+\t}\n+\n+\tpublic void testCombinedRangesInOneGroupCase2() throws Exception {\n+\t\tassertMatch(\"[a-c-e]\", \"e\", true, false);\n+\t}\n+\n+\tpublic void testInversedGroupCase0() throws Exception {\n+\t\tassertMatch(\"[!b-c]\", \"a\", true, false);\n+\t}\n+\n+\tpublic void testInversedGroupCase1() throws Exception {\n+\t\tassertMatch(\"[!b-c]\", \"b\", false, false);\n+\t}\n+\n+\tpublic void testInversedGroupCase2() throws Exception {\n+\t\tassertMatch(\"[!b-c]\", \"c\", false, false);\n+\t}\n+\n+\tpublic void testInversedGroupCase3() throws Exception {\n+\t\tassertMatch(\"[!b-c]\", \"d\", true, false);\n+\t}\n+\n+\tpublic void testAlphaGroupCase0() throws Exception {\n+\t\tassertMatch(\"[[:alpha:]]\", \"d\", true, false);\n+\t}\n+\n+\tpublic void testAlphaGroupCase1() throws Exception {\n+\t\tassertMatch(\"[[:alpha:]]\", \":\", false, false);\n+\t}\n+\n+\tpublic void testAlphaGroupCase2() throws Exception {\n+\t\tassertMatch(\"[[:alpha:]]\", \"Ã¶\", true, false);\n+\t}\n+\n+\tpublic void test2AlphaGroupsCase0() throws Exception {\n+\t\tassertMatch(\"[[:alpha:]][[:alpha:]]\", \"aÃ¶\", true, false);\n+\t\tassertMatch(\"[[:alpha:]][[:alpha:]]\", \"a1\", false, false);\n+\t}\n+\n+\tpublic void testAlnumGroupCase0() throws Exception {\n+\t\tassertMatch(\"[[:alnum:]]\", \"a\", true, false);\n+\t}\n+\n+\tpublic void testAlnumGroupCase1() throws Exception {\n+\t\tassertMatch(\"[[:alnum:]]\", \"1\", true, false);\n+\t}\n+\n+\tpublic void testAlnumGroupCase2() throws Exception {\n+\t\tassertMatch(\"[[:alnum:]]\", \":\", false, false);\n+\t}\n+\n+\tpublic void testBlankGroupCase0() throws Exception {\n+\t\tassertMatch(\"[[:blank:]]\", \" \", true, false);\n+\t}\n+\n+\tpublic void testBlankGroupCase1() throws Exception {\n+\t\tassertMatch(\"[[:blank:]]\", \"\\t\", true, false);\n+\t}\n+\n+\tpublic void testBlankGroupCase2() throws Exception {\n+\t\tassertMatch(\"[[:blank:]]\", \"\\r\", false, false);\n+\t}\n+\n+\tpublic void testBlankGroupCase3() throws Exception {\n+\t\tassertMatch(\"[[:blank:]]\", \"\\n\", false, false);\n+\t}\n+\n+\tpublic void testBlankGroupCase4() throws Exception {\n+\t\tassertMatch(\"[[:blank:]]\", \"a\", false, false);\n+\t}\n+\n+\tpublic void testCntrlGroupCase0() throws Exception {\n+\t\tassertMatch(\"[[:cntrl:]]\", \"a\", false, false);\n+\t}\n+\n+\tpublic void testCntrlGroupCase1() throws Exception {\n+\t\tassertMatch(\"[[:cntrl:]]\", String.valueOf((char) 7), true, false);\n+\t}\n+\n+\tpublic void testDigitGroupCase0() throws Exception {\n+\t\tassertMatch(\"[[:digit:]]\", \"0\", true, false);\n+\t}\n+\n+\tpublic void testDigitGroupCase1() throws Exception {\n+\t\tassertMatch(\"[[:digit:]]\", \"5\", true, false);\n+\t}\n+\n+\tpublic void testDigitGroupCase2() throws Exception {\n+\t\tassertMatch(\"[[:digit:]]\", \"9\", true, false);\n+\t}\n+\n+\tpublic void testDigitGroupCase3() throws Exception {\n+\t\tassertMatch(\"[[:digit:]]\", \"Û¹\", true, false);\n+\t}\n+\n+\tpublic void testDigitGroupCase4() throws Exception {\n+\t\tassertMatch(\"[[:digit:]]\", \"a\", false, false);\n+\t}\n+\n+\tpublic void testDigitGroupCase5() throws Exception {\n+\t\tassertMatch(\"[[:digit:]]\", \"]\", false, false);\n+\t}\n+\n+\tpublic void testGraphGroupCase0() throws Exception {\n+\t\tassertMatch(\"[[:graph:]]\", \"]\", true, false);\n+\t}\n+\n+\tpublic void testGraphGroupCase1() throws Exception {\n+\t\tassertMatch(\"[[:graph:]]\", \"a\", true, false);\n+\t}\n+\n+\tpublic void testGraphGroupCase2() throws Exception {\n+\t\tassertMatch(\"[[:graph:]]\", \".\", true, false);\n+\t}\n+\n+\tpublic void testGraphGroupCase3() throws Exception {\n+\t\tassertMatch(\"[[:graph:]]\", \"0\", true, false);\n+\t}\n+\n+\tpublic void testGraphGroupCase4() throws Exception {\n+\t\tassertMatch(\"[[:graph:]]\", \" \", false, false);\n+\t}\n+\n+\tpublic void testGraphGroupCase5() throws Exception {\n+\t\tassertMatch(\"[[:graph:]]\", \"Ã¶\", true, false);\n+\t}\n+\n+\tpublic void testLowerGroupCase0() throws Exception {\n+\t\tassertMatch(\"[[:lower:]]\", \"a\", true, false);\n+\t}\n+\n+\tpublic void testLowerGroupCase1() throws Exception {\n+\t\tassertMatch(\"[[:lower:]]\", \"h\", true, false);\n+\t}\n+\n+\tpublic void testLowerGroupCase2() throws Exception {\n+\t\tassertMatch(\"[[:lower:]]\", \"A\", false, false);\n+\t}\n+\n+\tpublic void testLowerGroupCase3() throws Exception {\n+\t\tassertMatch(\"[[:lower:]]\", \"H\", false, false);\n+\t}\n+\n+\tpublic void testLowerGroupCase4() throws Exception {\n+\t\tassertMatch(\"[[:lower:]]\", \"Ã¤\", true, false);\n+\t}\n+\n+\tpublic void testLowerGroupCase5() throws Exception {\n+\t\tassertMatch(\"[[:lower:]]\", \".\", false, false);\n+\t}\n+\n+\tpublic void testPrintGroupCase0() throws Exception {\n+\t\tassertMatch(\"[[:print:]]\", \"]\", true, false);\n+\t}\n+\n+\tpublic void testPrintGroupCase1() throws Exception {\n+\t\tassertMatch(\"[[:print:]]\", \"a\", true, false);\n+\t}\n+\n+\tpublic void testPrintGroupCase2() throws Exception {\n+\t\tassertMatch(\"[[:print:]]\", \".\", true, false);\n+\t}\n+\n+\tpublic void testPrintGroupCase3() throws Exception {\n+\t\tassertMatch(\"[[:print:]]\", \"0\", true, false);\n+\t}\n+\n+\tpublic void testPrintGroupCase4() throws Exception {\n+\t\tassertMatch(\"[[:print:]]\", \" \", true, false);\n+\t}\n+\n+\tpublic void testPrintGroupCase5() throws Exception {\n+\t\tassertMatch(\"[[:print:]]\", \"Ã¶\", true, false);\n+\t}\n+\n+\tpublic void testPunctGroupCase0() throws Exception {\n+\t\tassertMatch(\"[[:punct:]]\", \".\", true, false);\n+\t}\n+\n+\tpublic void testPunctGroupCase1() throws Exception {\n+\t\tassertMatch(\"[[:punct:]]\", \"@\", true, false);\n+\t}\n+\n+\tpublic void testPunctGroupCase2() throws Exception {\n+\t\tassertMatch(\"[[:punct:]]\", \" \", false, false);\n+\t}\n+\n+\tpublic void testPunctGroupCase3() throws Exception {\n+\t\tassertMatch(\"[[:punct:]]\", \"a\", false, false);\n+\t}\n+\n+\tpublic void testSpaceGroupCase0() throws Exception {\n+\t\tassertMatch(\"[[:space:]]\", \" \", true, false);\n+\t}\n+\n+\tpublic void testSpaceGroupCase1() throws Exception {\n+\t\tassertMatch(\"[[:space:]]\", \"\\t\", true, false);\n+\t}\n+\n+\tpublic void testSpaceGroupCase2() throws Exception {\n+\t\tassertMatch(\"[[:space:]]\", \"\\r\", true, false);\n+\t}\n+\n+\tpublic void testSpaceGroupCase3() throws Exception {\n+\t\tassertMatch(\"[[:space:]]\", \"\\n\", true, false);\n+\t}\n+\n+\tpublic void testSpaceGroupCase4() throws Exception {\n+\t\tassertMatch(\"[[:space:]]\", \"a\", false, false);\n+\t}\n+\n+\tpublic void testUpperGroupCase0() throws Exception {\n+\t\tassertMatch(\"[[:upper:]]\", \"a\", false, false);\n+\t}\n+\n+\tpublic void testUpperGroupCase1() throws Exception {\n+\t\tassertMatch(\"[[:upper:]]\", \"h\", false, false);\n+\t}\n+\n+\tpublic void testUpperGroupCase2() throws Exception {\n+\t\tassertMatch(\"[[:upper:]]\", \"A\", true, false);\n+\t}\n+\n+\tpublic void testUpperGroupCase3() throws Exception {\n+\t\tassertMatch(\"[[:upper:]]\", \"H\", true, false);\n+\t}\n+\n+\tpublic void testUpperGroupCase4() throws Exception {\n+\t\tassertMatch(\"[[:upper:]]\", \"Ã\", true, false);\n+\t}\n+\n+\tpublic void testUpperGroupCase5() throws Exception {\n+\t\tassertMatch(\"[[:upper:]]\", \".\", false, false);\n+\t}\n+\n+\tpublic void testXDigitGroupCase0() throws Exception {\n+\t\tassertMatch(\"[[:xdigit:]]\", \"a\", true, false);\n+\t}\n+\n+\tpublic void testXDigitGroupCase1() throws Exception {\n+\t\tassertMatch(\"[[:xdigit:]]\", \"d\", true, false);\n+\t}\n+\n+\tpublic void testXDigitGroupCase2() throws Exception {\n+\t\tassertMatch(\"[[:xdigit:]]\", \"f\", true, false);\n+\t}\n+\n+\tpublic void testXDigitGroupCase3() throws Exception {\n+\t\tassertMatch(\"[[:xdigit:]]\", \"0\", true, false);\n+\t}\n+\n+\tpublic void testXDigitGroupCase4() throws Exception {\n+\t\tassertMatch(\"[[:xdigit:]]\", \"5\", true, false);\n+\t}\n+\n+\tpublic void testXDigitGroupCase5() throws Exception {\n+\t\tassertMatch(\"[[:xdigit:]]\", \"9\", true, false);\n+\t}\n+\n+\tpublic void testXDigitGroupCase6() throws Exception {\n+\t\tassertMatch(\"[[:xdigit:]]\", \"Û¹\", false, false);\n+\t}\n+\n+\tpublic void testXDigitGroupCase7() throws Exception {\n+\t\tassertMatch(\"[[:xdigit:]]\", \".\", false, false);\n+\t}\n+\n+\tpublic void testWordroupCase0() throws Exception {\n+\t\tassertMatch(\"[[:word:]]\", \"g\", true, false);\n+\t}\n+\n+\tpublic void testWordroupCase1() throws Exception {\n+\t\tassertMatch(\"[[:word:]]\", \"Ã¶\", true, false);\n+\t}\n+\n+\tpublic void testWordroupCase2() throws Exception {\n+\t\tassertMatch(\"[[:word:]]\", \"5\", true, false);\n+\t}\n+\n+\tpublic void testWordroupCase3() throws Exception {\n+\t\tassertMatch(\"[[:word:]]\", \"_\", true, false);\n+\t}\n+\n+\tpublic void testWordroupCase4() throws Exception {\n+\t\tassertMatch(\"[[:word:]]\", \" \", false, false);\n+\t}\n+\n+\tpublic void testWordroupCase5() throws Exception {\n+\t\tassertMatch(\"[[:word:]]\", \".\", false, false);\n+\t}\n+\n+\tpublic void testSpecialGroupCase0() throws Exception {\n+\t\tassertMatch(\"[[]\", \"[\", true, false);\n+\t}\n+\n+\tpublic void testSpecialGroupCase1() throws Exception {\n+\t\tassertMatch(\"[]]\", \"]\", true, false);\n+\t}\n+\n+\tpublic void testSpecialGroupCase2() throws Exception {\n+\t\tassertMatch(\"[]a]\", \"]\", true, false);\n+\t}\n+\n+\tpublic void testSpecialGroupCase3() throws Exception {\n+\t\tassertMatch(\"[a[]\", \"[\", true, false);\n+\t}\n+\n+\tpublic void testSpecialGroupCase4() throws Exception {\n+\t\tassertMatch(\"[a[]\", \"a\", true, false);\n+\t}\n+\n+\tpublic void testSpecialGroupCase5() throws Exception {\n+\t\tassertMatch(\"[!]]\", \"]\", false, false);\n+\t}\n+\n+\tpublic void testSpecialGroupCase6() throws Exception {\n+\t\tassertMatch(\"[!]]\", \"x\", true, false);\n+\t}\n+\n+\tpublic void testSpecialGroupCase7() throws Exception {\n+\t\tassertMatch(\"[:]]\", \":]\", true, false);\n+\t}\n+\n+\tpublic void testSpecialGroupCase8() throws Exception {\n+\t\tassertMatch(\"[:]]\", \":\", false, true);\n+\t}\n+\n+\tpublic void testSpecialGroupCase9() throws Exception {\n+\t\ttry {\n+\t\t\tassertMatch(\"[[:]\", \":\", true, true);\n+\t\t\tfail(\"InvalidPatternException expected\");\n+\t\t} catch (InvalidPatternException e) {\n+\t\t\t// expected\n+\t\t}\n+\t}\n+\n+\tpublic void testUnsupportedGroupCase0() throws Exception {\n+\t\ttry {\n+\t\t\tassertMatch(\"[[=a=]]\", \"b\", false, false);\n+\t\t\tfail(\"InvalidPatternException expected\");\n+\t\t} catch (InvalidPatternException e) {\n+\t\t\tassertTrue(e.getMessage().contains(\"[=a=]\"));\n+\t\t}\n+\t}\n+\n+\tpublic void testUnsupportedGroupCase1() throws Exception {\n+\t\ttry {\n+\t\t\tassertMatch(\"[[.a.]]\", \"b\", false, false);\n+\t\t\tfail(\"InvalidPatternException expected\");\n+\t\t} catch (InvalidPatternException e) {\n+\t\t\tassertTrue(e.getMessage().contains(\"[.a.]\"));\n+\t\t}\n+\t}\n+\n+\tpublic void testFilePathSimpleCase() throws Exception {\n+\t\tassertFileNameMatch(\"a/b\", \"a/b\", '/', true, false);\n+\t}\n+\n+\tpublic void testFilePathCase0() throws Exception {\n+\t\tassertFileNameMatch(\"a*b\", \"a/b\", '/', false, false);\n+\t}\n+\n+\tpublic void testFilePathCase1() throws Exception {\n+\t\tassertFileNameMatch(\"a?b\", \"a/b\", '/', false, false);\n+\t}\n+\n+\tpublic void testFilePathCase2() throws Exception {\n+\t\tassertFileNameMatch(\"a*b\", \"a\\\\b\", '\\\\', false, false);\n+\t}\n+\n+\tpublic void testFilePathCase3() throws Exception {\n+\t\tassertFileNameMatch(\"a?b\", \"a\\\\b\", '\\\\', false, false);\n+\t}\n+\n+\tpublic void testReset() throws Exception {\n+\t\tfinal String pattern = \"helloworld\";\n+\t\tfinal FileNameMatcher matcher = new FileNameMatcher(pattern, null);\n+\t\tmatcher.append(\"helloworld\");\n+\t\tassertEquals(true, matcher.isMatch());\n+\t\tassertEquals(false, matcher.canAppendMatch());\n+\t\tmatcher.reset();\n+\t\tmatcher.append(\"hello\");\n+\t\tassertEquals(false, matcher.isMatch());\n+\t\tassertEquals(true, matcher.canAppendMatch());\n+\t\tmatcher.append(\"world\");\n+\t\tassertEquals(true, matcher.isMatch());\n+\t\tassertEquals(false, matcher.canAppendMatch());\n+\t\tmatcher.append(\"to much\");\n+\t\tassertEquals(false, matcher.isMatch());\n+\t\tassertEquals(false, matcher.canAppendMatch());\n+\t\tmatcher.reset();\n+\t\tmatcher.append(\"helloworld\");\n+\t\tassertEquals(true, matcher.isMatch());\n+\t\tassertEquals(false, matcher.canAppendMatch());\n+\t}\n+\n+\tpublic void testCreateMatcherForSuffix() throws Exception {\n+\t\tfinal String pattern = \"helloworld\";\n+\t\tfinal FileNameMatcher matcher = new FileNameMatcher(pattern, null);\n+\t\tmatcher.append(\"hello\");\n+\t\tfinal FileNameMatcher childMatcher = matcher.createMatcherForSuffix();\n+\t\tassertEquals(false, matcher.isMatch());\n+\t\tassertEquals(true, matcher.canAppendMatch());\n+\t\tassertEquals(false, childMatcher.isMatch());\n+\t\tassertEquals(true, childMatcher.canAppendMatch());\n+\t\tmatcher.append(\"world\");\n+\t\tassertEquals(true, matcher.isMatch());\n+\t\tassertEquals(false, matcher.canAppendMatch());\n+\t\tassertEquals(false, childMatcher.isMatch());\n+\t\tassertEquals(true, childMatcher.canAppendMatch());\n+\t\tchildMatcher.append(\"world\");\n+\t\tassertEquals(true, matcher.isMatch());\n+\t\tassertEquals(false, matcher.canAppendMatch());\n+\t\tassertEquals(true, childMatcher.isMatch());\n+\t\tassertEquals(false, childMatcher.canAppendMatch());\n+\t\tchildMatcher.reset();\n+\t\tassertEquals(true, matcher.isMatch());\n+\t\tassertEquals(false, matcher.canAppendMatch());\n+\t\tassertEquals(false, childMatcher.isMatch());\n+\t\tassertEquals(true, childMatcher.canAppendMatch());\n+\t\tchildMatcher.append(\"world\");\n+\t\tassertEquals(true, matcher.isMatch());\n+\t\tassertEquals(false, matcher.canAppendMatch());\n+\t\tassertEquals(true, childMatcher.isMatch());\n+\t\tassertEquals(false, childMatcher.canAppendMatch());\n+\t}\n+}\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/errors/InvalidPatternException.java b/org.spearce.jgit/src/org/spearce/jgit/errors/InvalidPatternException.java\nnew file mode 100644\nindex 0000000..02f67fe\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/errors/InvalidPatternException.java\n@@ -0,0 +1,65 @@\n+/*\n+ * Copyright (C) 2008, Florian KÃ¶berle <florianskarten@web.de>\n+ *\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or\n+ * without modification, are permitted provided that the following\n+ * conditions are met:\n+ *\n+ * - Redistributions of source code must retain the above copyright\n+ *   notice, this list of conditions and the following disclaimer.\n+ *\n+ * - Redistributions in binary form must reproduce the above\n+ *   copyright notice, this list of conditions and the following\n+ *   disclaimer in the documentation and/or other materials provided\n+ *   with the distribution.\n+ *\n+ * - Neither the name of the Git Development Community nor the\n+ *   names of its contributors may be used to endorse or promote\n+ *   products derived from this software without specific prior\n+ *   written permission.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n+ * CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+package org.spearce.jgit.errors;\n+\n+/**\n+ * Thrown when a pattern passed in an argument was wrong.\n+ * \n+ */\n+public class InvalidPatternException extends Exception {\n+\tprivate final String pattern;\n+\n+\t/**\n+\t * @param message\n+\t *            explains what was wrong with the pattern.\n+\t * @param pattern\n+\t *            the invalid pattern.\n+\t */\n+\tpublic InvalidPatternException(String message, String pattern) {\n+\t\tsuper(message);\n+\t\tthis.pattern = pattern;\n+\t}\n+\n+\t/**\n+\t * @return the invalid pattern.\n+\t */\n+\tpublic String getPattern() {\n+\t\treturn pattern;\n+\t}\n+\n+}\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/errors/NoClosingBracketException.java b/org.spearce.jgit/src/org/spearce/jgit/errors/NoClosingBracketException.java\nnew file mode 100644\nindex 0000000..1a93906\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/errors/NoClosingBracketException.java\n@@ -0,0 +1,69 @@\n+/*\n+ * Copyright (C) 2008, Florian KÃ¶berle <florianskarten@web.de>\n+ *\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or\n+ * without modification, are permitted provided that the following\n+ * conditions are met:\n+ *\n+ * - Redistributions of source code must retain the above copyright\n+ *   notice, this list of conditions and the following disclaimer.\n+ *\n+ * - Redistributions in binary form must reproduce the above\n+ *   copyright notice, this list of conditions and the following\n+ *   disclaimer in the documentation and/or other materials provided\n+ *   with the distribution.\n+ *\n+ * - Neither the name of the Git Development Community nor the\n+ *   names of its contributors may be used to endorse or promote\n+ *   products derived from this software without specific prior\n+ *   written permission.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n+ * CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+package org.spearce.jgit.errors;\n+\n+/**\n+ * Thrown when a pattern contains a character group which is open to the right\n+ * side or a character class which is open to the right side.\n+ */\n+public class NoClosingBracketException extends InvalidPatternException {\n+\n+\t/**\n+\t * @param indexOfOpeningBracket\n+\t *            the position of the [ character which has no ] character.\n+\t * @param openingBracket\n+\t *            the unclosed bracket.\n+\t * @param closingBracket\n+\t *            the missing closing bracket.\n+\t * @param pattern\n+\t *            the invalid pattern.\n+\t */\n+\tpublic NoClosingBracketException(final int indexOfOpeningBracket,\n+\t\t\tfinal String openingBracket, final String closingBracket,\n+\t\t\tfinal String pattern) {\n+\t\tsuper(createMessage(indexOfOpeningBracket, openingBracket,\n+\t\t\t\tclosingBracket), pattern);\n+\t}\n+\n+\tprivate static String createMessage(final int indexOfOpeningBracket,\n+\t\t\tfinal String openingBracket, final String closingBracket) {\n+\t\treturn String.format(\"No closing %s found for %s at index %s.\",\n+\t\t\t\tclosingBracket, openingBracket, new Integer(\n+\t\t\t\t\t\tindexOfOpeningBracket));\n+\t}\n+}\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/fnmatch/AbstractHead.java b/org.spearce.jgit/src/org/spearce/jgit/fnmatch/AbstractHead.java\nnew file mode 100644\nindex 0000000..1e9a0ca\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/fnmatch/AbstractHead.java\n@@ -0,0 +1,74 @@\n+/*\n+ * Copyright (C) 2008, Florian KÃ¶berle <florianskarten@web.de>\n+ *\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or\n+ * without modification, are permitted provided that the following\n+ * conditions are met:\n+ *\n+ * - Redistributions of source code must retain the above copyright\n+ *   notice, this list of conditions and the following disclaimer.\n+ *\n+ * - Redistributions in binary form must reproduce the above\n+ *   copyright notice, this list of conditions and the following\n+ *   disclaimer in the documentation and/or other materials provided\n+ *   with the distribution.\n+ *\n+ * - Neither the name of the Git Development Community nor the\n+ *   names of its contributors may be used to endorse or promote\n+ *   products derived from this software without specific prior\n+ *   written permission.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n+ * CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+package org.spearce.jgit.fnmatch;\n+\n+import java.util.List;\n+\n+abstract class AbstractHead implements Head {\n+\tprivate List<Head> newHeads = null;\n+\n+\tprivate final boolean star;\n+\n+\tprotected abstract boolean matches(char c);\n+\n+\tAbstractHead(boolean star) {\n+\t\tthis.star = star;\n+\t}\n+\n+\t/**\n+\t * \n+\t * @param newHeads\n+\t *            a list of {@link Head}s which will not be modified.\n+\t */\n+\tpublic final void setNewHeads(List<Head> newHeads) {\n+\t\tif (this.newHeads != null)\n+\t\t\tthrow new IllegalStateException(\"Property is already non null\");\n+\t\tthis.newHeads = newHeads;\n+\t}\n+\n+\tpublic List<Head> getNextHeads(char c) {\n+\t\tif (matches(c))\n+\t\t\treturn newHeads;\n+\t\telse\n+\t\t\treturn FileNameMatcher.EMPTY_HEAD_LIST;\n+\t}\n+\n+\tboolean isStar() {\n+\t\treturn star;\n+\t}\n+}\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/fnmatch/CharacterHead.java b/org.spearce.jgit/src/org/spearce/jgit/fnmatch/CharacterHead.java\nnew file mode 100644\nindex 0000000..01c3403\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/fnmatch/CharacterHead.java\n@@ -0,0 +1,53 @@\n+/*\n+ * Copyright (C) 2008, Florian KÃ¶berle <florianskarten@web.de>\n+ *\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or\n+ * without modification, are permitted provided that the following\n+ * conditions are met:\n+ *\n+ * - Redistributions of source code must retain the above copyright\n+ *   notice, this list of conditions and the following disclaimer.\n+ *\n+ * - Redistributions in binary form must reproduce the above\n+ *   copyright notice, this list of conditions and the following\n+ *   disclaimer in the documentation and/or other materials provided\n+ *   with the distribution.\n+ *\n+ * - Neither the name of the Git Development Community nor the\n+ *   names of its contributors may be used to endorse or promote\n+ *   products derived from this software without specific prior\n+ *   written permission.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n+ * CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+package org.spearce.jgit.fnmatch;\n+\n+final class CharacterHead extends AbstractHead {\n+\tprivate final char expectedCharacter;\n+\n+\tprotected CharacterHead(final char expectedCharacter) {\n+\t\tsuper(false);\n+\t\tthis.expectedCharacter = expectedCharacter;\n+\t}\n+\n+\t@Override\n+\tprotected final boolean matches(final char c) {\n+\t\treturn c == expectedCharacter;\n+\t}\n+\n+}\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/fnmatch/FileNameMatcher.java b/org.spearce.jgit/src/org/spearce/jgit/fnmatch/FileNameMatcher.java\nnew file mode 100644\nindex 0000000..21fbf77\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/fnmatch/FileNameMatcher.java\n@@ -0,0 +1,327 @@\n+/*\n+ * Copyright (C) 2008, Florian KÃ¶berle <florianskarten@web.de>\n+ *\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or\n+ * without modification, are permitted provided that the following\n+ * conditions are met:\n+ *\n+ * - Redistributions of source code must retain the above copyright\n+ *   notice, this list of conditions and the following disclaimer.\n+ *\n+ * - Redistributions in binary form must reproduce the above\n+ *   copyright notice, this list of conditions and the following\n+ *   disclaimer in the documentation and/or other materials provided\n+ *   with the distribution.\n+ *\n+ * - Neither the name of the Git Development Community nor the\n+ *   names of its contributors may be used to endorse or promote\n+ *   products derived from this software without specific prior\n+ *   written permission.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n+ * CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+package org.spearce.jgit.fnmatch;\n+\n+import java.util.ArrayList;\n+import java.util.Collections;\n+import java.util.List;\n+import java.util.ListIterator;\n+import java.util.regex.Matcher;\n+import java.util.regex.Pattern;\n+\n+import org.spearce.jgit.errors.InvalidPatternException;\n+import org.spearce.jgit.errors.NoClosingBracketException;\n+\n+/**\n+ * This class can be used to match filenames against fnmatch like patterns. It\n+ * is not thread save.\n+ */\n+public class FileNameMatcher {\n+\tstatic final List<Head> EMPTY_HEAD_LIST = Collections.emptyList();\n+\n+\tprivate static final Pattern characterClassStartPattern = Pattern\n+\t\t\t.compile(\"\\\\[[.:=]\");\n+\n+\tprivate List<Head> headsStartValue;\n+\n+\tprivate List<Head> heads;\n+\n+\t/**\n+\t * {{@link #extendStringToMatchByOneCharacter(char)} needs a list for the\n+\t * new heads, allocating a new array would be bad for the performance, as\n+\t * the method gets called very often.\n+\t * \n+\t */\n+\tprivate List<Head> listForLocalUseage;\n+\n+\t/**\n+\t * \n+\t * @param headsStartValue\n+\t *            must be a list which will never be modified.\n+\t */\n+\tprivate FileNameMatcher(final List<Head> headsStartValue) {\n+\t\tthis.headsStartValue = headsStartValue;\n+\t\tthis.heads = new ArrayList<Head>(headsStartValue.size());\n+\t\tthis.heads.addAll(this.headsStartValue);\n+\t\tthis.listForLocalUseage = new ArrayList<Head>(headsStartValue.size());\n+\t}\n+\n+\t/**\n+\t * @param patternString\n+\t *            must contain a pattern which fnmatch would accept.\n+\t * @param invalidWildgetCharacter\n+\t *            if this parameter isn't null then this character will not\n+\t *            match at wildcards(* and ? are wildcards).\n+\t * @throws InvalidPatternException\n+\t *             if the patternString contains a invalid fnmatch pattern.\n+\t */\n+\tpublic FileNameMatcher(final String patternString,\n+\t\t\tfinal Character invalidWildgetCharacter)\n+\t\t\tthrows InvalidPatternException {\n+\t\tthis(createHeadsStartValues(patternString, invalidWildgetCharacter));\n+\t}\n+\n+\tprivate static List<Head> createHeadsStartValues(\n+\t\t\tfinal String patternString, final Character invalidWildgetCharacter)\n+\t\t\tthrows InvalidPatternException {\n+\n+\t\tfinal List<AbstractHead> allHeads = parseHeads(patternString,\n+\t\t\t\tinvalidWildgetCharacter);\n+\n+\t\tList<Head> nextHeadsSuggestion = new ArrayList<Head>(2);\n+\t\tnextHeadsSuggestion.add(LastHead.INSTANCE);\n+\t\tfor (int i = allHeads.size() - 1; i >= 0; i--) {\n+\t\t\tfinal AbstractHead head = allHeads.get(i);\n+\n+\t\t\t// explanation:\n+\t\t\t// a and * of the pattern \"a*b\"\n+\t\t\t// need *b as newHeads\n+\t\t\t// that's why * extends the list for it self and it's left neighbor.\n+\t\t\tif (head.isStar()) {\n+\t\t\t\tnextHeadsSuggestion.add(head);\n+\t\t\t\thead.setNewHeads(nextHeadsSuggestion);\n+\t\t\t} else {\n+\t\t\t\thead.setNewHeads(nextHeadsSuggestion);\n+\t\t\t\tnextHeadsSuggestion = new ArrayList<Head>(2);\n+\t\t\t\tnextHeadsSuggestion.add(head);\n+\t\t\t}\n+\t\t}\n+\t\treturn nextHeadsSuggestion;\n+\t}\n+\n+\tprivate static int findGroupEnd(final int indexOfStartBracket,\n+\t\t\tfinal String pattern) throws InvalidPatternException {\n+\t\tint firstValidCharClassIndex = indexOfStartBracket + 1;\n+\t\tint firstValidEndBracketIndex = indexOfStartBracket + 2;\n+\n+\t\tif (indexOfStartBracket + 1 >= pattern.length())\n+\t\t\tthrow new NoClosingBracketException(indexOfStartBracket, \"[\", \"]\",\n+\t\t\t\t\tpattern);\n+\n+\t\tif (pattern.charAt(firstValidCharClassIndex) == '!') {\n+\t\t\tfirstValidCharClassIndex++;\n+\t\t\tfirstValidEndBracketIndex++;\n+\t\t}\n+\n+\t\tfinal Matcher charClassStartMatcher = characterClassStartPattern\n+\t\t\t\t.matcher(pattern);\n+\n+\t\tint groupEnd = -1;\n+\t\twhile (groupEnd == -1) {\n+\n+\t\t\tfinal int possibleGroupEnd = pattern.indexOf(']',\n+\t\t\t\t\tfirstValidEndBracketIndex);\n+\t\t\tif (possibleGroupEnd == -1)\n+\t\t\t\tthrow new NoClosingBracketException(indexOfStartBracket, \"[\",\n+\t\t\t\t\t\t\"]\", pattern);\n+\n+\t\t\tfinal boolean foundCharClass = charClassStartMatcher\n+\t\t\t\t\t.find(firstValidCharClassIndex);\n+\n+\t\t\tif (foundCharClass\n+\t\t\t\t\t&& charClassStartMatcher.start() < possibleGroupEnd) {\n+\n+\t\t\t\tfinal String classStart = charClassStartMatcher.group(0);\n+\t\t\t\tfinal String classEnd = classStart.charAt(1) + \"]\";\n+\n+\t\t\t\tfinal int classStartIndex = charClassStartMatcher.start();\n+\t\t\t\tfinal int classEndIndex = pattern.indexOf(classEnd,\n+\t\t\t\t\t\tclassStartIndex + 2);\n+\n+\t\t\t\tif (classEndIndex == -1)\n+\t\t\t\t\tthrow new NoClosingBracketException(classStartIndex,\n+\t\t\t\t\t\t\tclassStart, classEnd, pattern);\n+\n+\t\t\t\tfirstValidCharClassIndex = classEndIndex + 2;\n+\t\t\t\tfirstValidEndBracketIndex = firstValidCharClassIndex;\n+\t\t\t} else {\n+\t\t\t\tgroupEnd = possibleGroupEnd;\n+\t\t\t}\n+\t\t}\n+\t\treturn groupEnd;\n+\t}\n+\n+\tprivate static List<AbstractHead> parseHeads(final String pattern,\n+\t\t\tfinal Character invalidWildgetCharacter)\n+\t\t\tthrows InvalidPatternException {\n+\n+\t\tint currentIndex = 0;\n+\t\tList<AbstractHead> heads = new ArrayList<AbstractHead>();\n+\t\twhile (currentIndex < pattern.length()) {\n+\t\t\tfinal int groupStart = pattern.indexOf('[', currentIndex);\n+\t\t\tif (groupStart == -1) {\n+\t\t\t\tfinal String patternPart = pattern.substring(currentIndex);\n+\t\t\t\theads.addAll(createSimpleHeads(patternPart,\n+\t\t\t\t\t\tinvalidWildgetCharacter));\n+\t\t\t\tcurrentIndex = pattern.length();\n+\t\t\t} else {\n+\t\t\t\tfinal String patternPart = pattern.substring(currentIndex,\n+\t\t\t\t\t\tgroupStart);\n+\t\t\t\theads.addAll(createSimpleHeads(patternPart,\n+\t\t\t\t\t\tinvalidWildgetCharacter));\n+\n+\t\t\t\tfinal int groupEnd = findGroupEnd(groupStart, pattern);\n+\t\t\t\tfinal String groupPart = pattern.substring(groupStart + 1,\n+\t\t\t\t\t\tgroupEnd);\n+\t\t\t\theads.add(new GroupHead(groupPart, pattern));\n+\t\t\t\tcurrentIndex = groupEnd + 1;\n+\t\t\t}\n+\t\t}\n+\t\treturn heads;\n+\t}\n+\n+\tprivate static List<AbstractHead> createSimpleHeads(\n+\t\t\tfinal String patternPart, final Character invalidWildgetCharacter) {\n+\t\tfinal List<AbstractHead> heads = new ArrayList<AbstractHead>(\n+\t\t\t\tpatternPart.length());\n+\t\tfor (int i = 0; i < patternPart.length(); i++) {\n+\t\t\tfinal char c = patternPart.charAt(i);\n+\t\t\tswitch (c) {\n+\t\t\tcase '*': {\n+\t\t\t\tfinal AbstractHead head = createWildCardHead(\n+\t\t\t\t\t\tinvalidWildgetCharacter, true);\n+\t\t\t\theads.add(head);\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t\tcase '?': {\n+\t\t\t\tfinal AbstractHead head = createWildCardHead(\n+\t\t\t\t\t\tinvalidWildgetCharacter, false);\n+\t\t\t\theads.add(head);\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t\tdefault:\n+\t\t\t\tfinal CharacterHead head = new CharacterHead(c);\n+\t\t\t\theads.add(head);\n+\t\t\t}\n+\t\t}\n+\t\treturn heads;\n+\t}\n+\n+\tprivate static AbstractHead createWildCardHead(\n+\t\t\tfinal Character invalidWildgetCharacter, final boolean star) {\n+\t\tif (invalidWildgetCharacter != null)\n+\t\t\treturn new RestrictedWildCardHead(invalidWildgetCharacter\n+\t\t\t\t\t.charValue(), star);\n+\t\telse\n+\t\t\treturn new WildCardHead(star);\n+\t}\n+\n+\tprivate void extendStringToMatchByOneCharacter(final char c) {\n+\t\tfinal List<Head> newHeads = listForLocalUseage;\n+\t\tnewHeads.clear();\n+\t\tList<Head> lastAddedHeads = null;\n+\t\tfor (int i = 0; i < heads.size(); i++) {\n+\t\t\tfinal Head head = heads.get(i);\n+\t\t\tfinal List<Head> headsToAdd = head.getNextHeads(c);\n+\t\t\t// Why the next performance optimization isn't wrong:\n+\t\t\t// Some times two heads return the very same list.\n+\t\t\t// We save future effort if we don't add these heads again.\n+\t\t\t// This is the case with the heads \"a\" and \"*\" of \"a*b\" which\n+\t\t\t// both can return the list [\"*\",\"b\"]\n+\t\t\tif (headsToAdd != lastAddedHeads) {\n+\t\t\t\tnewHeads.addAll(headsToAdd);\n+\t\t\t\tlastAddedHeads = headsToAdd;\n+\t\t\t}\n+\t\t}\n+\t\tlistForLocalUseage = heads;\n+\t\theads = newHeads;\n+\t}\n+\n+\t/**\n+\t * \n+\t * @param stringToMatch\n+\t *            extends the string which is matched against the patterns of\n+\t *            this class.\n+\t */\n+\tpublic void append(final String stringToMatch) {\n+\t\tfor (int i = 0; i < stringToMatch.length(); i++) {\n+\t\t\tfinal char c = stringToMatch.charAt(i);\n+\t\t\textendStringToMatchByOneCharacter(c);\n+\t\t}\n+\t}\n+\n+\t/**\n+\t * Resets this matcher to it's state right after construction.\n+\t */\n+\tpublic void reset() {\n+\t\theads.clear();\n+\t\theads.addAll(headsStartValue);\n+\t}\n+\n+\t/**\n+\t * \n+\t * @return a {@link FileNameMatcher} instance which uses the same pattern\n+\t *         like this matcher, but has the current state of this matcher as\n+\t *         reset and start point.\n+\t */\n+\tpublic FileNameMatcher createMatcherForSuffix() {\n+\t\tfinal List<Head> copyOfHeads = new ArrayList<Head>(heads.size());\n+\t\tcopyOfHeads.addAll(heads);\n+\t\treturn new FileNameMatcher(copyOfHeads);\n+\t}\n+\n+\t/**\n+\t * \n+\t * @return true, if the string currently being matched does match.\n+\t */\n+\tpublic boolean isMatch() {\n+\t\tfinal ListIterator<Head> headIterator = heads\n+\t\t\t\t.listIterator(heads.size());\n+\t\twhile (headIterator.hasPrevious()) {\n+\t\t\tfinal Head head = headIterator.previous();\n+\t\t\tif (head == LastHead.INSTANCE) {\n+\t\t\t\treturn true;\n+\t\t\t}\n+\t\t}\n+\t\treturn false;\n+\t}\n+\n+\t/**\n+\t * \n+\t * @return false, if the string being matched will not match when the string\n+\t *         gets extended.\n+\t */\n+\tpublic boolean canAppendMatch() {\n+\t\tfor (int i = 0; i < heads.size(); i++) {\n+\t\t\tif (heads.get(i) != LastHead.INSTANCE) {\n+\t\t\t\treturn true;\n+\t\t\t}\n+\t\t}\n+\t\treturn false;\n+\t}\n+}\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/fnmatch/GroupHead.java b/org.spearce.jgit/src/org/spearce/jgit/fnmatch/GroupHead.java\nnew file mode 100644\nindex 0000000..9f72010\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/fnmatch/GroupHead.java\n@@ -0,0 +1,220 @@\n+/*\n+ * Copyright (C) 2008, Florian KÃ¶berle <florianskarten@web.de>\n+ *\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or\n+ * without modification, are permitted provided that the following\n+ * conditions are met:\n+ *\n+ * - Redistributions of source code must retain the above copyright\n+ *   notice, this list of conditions and the following disclaimer.\n+ *\n+ * - Redistributions in binary form must reproduce the above\n+ *   copyright notice, this list of conditions and the following\n+ *   disclaimer in the documentation and/or other materials provided\n+ *   with the distribution.\n+ *\n+ * - Neither the name of the Git Development Community nor the\n+ *   names of its contributors may be used to endorse or promote\n+ *   products derived from this software without specific prior\n+ *   written permission.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n+ * CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+package org.spearce.jgit.fnmatch;\n+\n+import java.util.ArrayList;\n+import java.util.List;\n+import java.util.regex.Matcher;\n+import java.util.regex.Pattern;\n+\n+import org.spearce.jgit.errors.InvalidPatternException;\n+\n+final class GroupHead extends AbstractHead {\n+\tprivate final List<CharacterPattern> characterClasses;\n+\n+\tprivate static final Pattern REGEX_PATTERN = Pattern\n+\t\t\t.compile(\"([^-][-][^-]|\\\\[[.:=].*?[.:=]\\\\])\");\n+\n+\tprivate final boolean inverse;\n+\n+\tGroupHead(String pattern, final String wholePattern)\n+\t\t\tthrows InvalidPatternException {\n+\t\tsuper(false);\n+\t\tthis.characterClasses = new ArrayList<CharacterPattern>();\n+\t\tthis.inverse = pattern.startsWith(\"!\");\n+\t\tif (inverse) {\n+\t\t\tpattern = pattern.substring(1);\n+\t\t}\n+\t\tfinal Matcher matcher = REGEX_PATTERN.matcher(pattern);\n+\t\twhile (matcher.find()) {\n+\t\t\tfinal String characterClass = matcher.group(0);\n+\t\t\tif (characterClass.length() == 3 && characterClass.charAt(1) == '-') {\n+\t\t\t\tfinal char start = characterClass.charAt(0);\n+\t\t\t\tfinal char end = characterClass.charAt(2);\n+\t\t\t\tcharacterClasses.add(new CharacterRange(start, end));\n+\t\t\t} else if (characterClass.equals(\"[:alnum:]\")) {\n+\t\t\t\tcharacterClasses.add(LetterPattern.INSTANCE);\n+\t\t\t\tcharacterClasses.add(DigitPattern.INSTANCE);\n+\t\t\t} else if (characterClass.equals(\"[:alpha:]\")) {\n+\t\t\t\tcharacterClasses.add(LetterPattern.INSTANCE);\n+\t\t\t} else if (characterClass.equals(\"[:blank:]\")) {\n+\t\t\t\tcharacterClasses.add(new OneCharacterPattern(' '));\n+\t\t\t\tcharacterClasses.add(new OneCharacterPattern('\\t'));\n+\t\t\t} else if (characterClass.equals(\"[:cntrl:]\")) {\n+\t\t\t\tcharacterClasses.add(new CharacterRange('\\u0000', '\\u001F'));\n+\t\t\t\tcharacterClasses.add(new OneCharacterPattern('\\u007F'));\n+\t\t\t} else if (characterClass.equals(\"[:digit:]\")) {\n+\t\t\t\tcharacterClasses.add(DigitPattern.INSTANCE);\n+\t\t\t} else if (characterClass.equals(\"[:graph:]\")) {\n+\t\t\t\tcharacterClasses.add(new CharacterRange('\\u0021', '\\u007E'));\n+\t\t\t\tcharacterClasses.add(LetterPattern.INSTANCE);\n+\t\t\t\tcharacterClasses.add(DigitPattern.INSTANCE);\n+\t\t\t} else if (characterClass.equals(\"[:lower:]\")) {\n+\t\t\t\tcharacterClasses.add(LowerPattern.INSTANCE);\n+\t\t\t} else if (characterClass.equals(\"[:print:]\")) {\n+\t\t\t\tcharacterClasses.add(new CharacterRange('\\u0020', '\\u007E'));\n+\t\t\t\tcharacterClasses.add(LetterPattern.INSTANCE);\n+\t\t\t\tcharacterClasses.add(DigitPattern.INSTANCE);\n+\t\t\t} else if (characterClass.equals(\"[:punct:]\")) {\n+\t\t\t\tcharacterClasses.add(PunctPattern.INSTANCE);\n+\t\t\t} else if (characterClass.equals(\"[:space:]\")) {\n+\t\t\t\tcharacterClasses.add(WhitespacePattern.INSTANCE);\n+\t\t\t} else if (characterClass.equals(\"[:upper:]\")) {\n+\t\t\t\tcharacterClasses.add(UpperPattern.INSTANCE);\n+\t\t\t} else if (characterClass.equals(\"[:xdigit:]\")) {\n+\t\t\t\tcharacterClasses.add(new CharacterRange('0', '9'));\n+\t\t\t\tcharacterClasses.add(new CharacterRange('a', 'f'));\n+\t\t\t\tcharacterClasses.add(new CharacterRange('A', 'F'));\n+\t\t\t} else if (characterClass.equals(\"[:word:]\")) {\n+\t\t\t\tcharacterClasses.add(new OneCharacterPattern('_'));\n+\t\t\t\tcharacterClasses.add(LetterPattern.INSTANCE);\n+\t\t\t\tcharacterClasses.add(DigitPattern.INSTANCE);\n+\t\t\t} else {\n+\t\t\t\tfinal String message = String.format(\n+\t\t\t\t\t\t\"The character class %s is not supported.\",\n+\t\t\t\t\t\tcharacterClass);\n+\t\t\t\tthrow new InvalidPatternException(message, wholePattern);\n+\t\t\t}\n+\n+\t\t\tpattern = matcher.replaceFirst(\"\");\n+\t\t\tmatcher.reset(pattern);\n+\t\t}\n+\t\t// pattern contains now no ranges\n+\t\tfor (int i = 0; i < pattern.length(); i++) {\n+\t\t\tfinal char c = pattern.charAt(i);\n+\t\t\tcharacterClasses.add(new OneCharacterPattern(c));\n+\t\t}\n+\t}\n+\n+\t@Override\n+\tprotected final boolean matches(final char c) {\n+\t\tfor (CharacterPattern pattern : characterClasses) {\n+\t\t\tif (pattern.matches(c)) {\n+\t\t\t\treturn !inverse;\n+\t\t\t}\n+\t\t}\n+\t\treturn inverse;\n+\t}\n+\n+\tprivate interface CharacterPattern {\n+\t\t/**\n+\t\t * @param c\n+\t\t *            the character to test\n+\t\t * @return returns true if the character matches a pattern.\n+\t\t */\n+\t\tboolean matches(char c);\n+\t}\n+\n+\tprivate static final class CharacterRange implements CharacterPattern {\n+\t\tprivate final char start;\n+\n+\t\tprivate final char end;\n+\n+\t\tCharacterRange(char start, char end) {\n+\t\t\tthis.start = start;\n+\t\t\tthis.end = end;\n+\t\t}\n+\n+\t\tpublic final boolean matches(char c) {\n+\t\t\treturn start <= c && c <= end;\n+\t\t}\n+\t}\n+\n+\tprivate static final class DigitPattern implements CharacterPattern {\n+\t\tstatic final GroupHead.DigitPattern INSTANCE = new DigitPattern();\n+\n+\t\tpublic final boolean matches(char c) {\n+\t\t\treturn Character.isDigit(c);\n+\t\t}\n+\t}\n+\n+\tprivate static final class LetterPattern implements CharacterPattern {\n+\t\tstatic final GroupHead.LetterPattern INSTANCE = new LetterPattern();\n+\n+\t\tpublic final boolean matches(char c) {\n+\t\t\treturn Character.isLetter(c);\n+\t\t}\n+\t}\n+\n+\tprivate static final class LowerPattern implements CharacterPattern {\n+\t\tstatic final GroupHead.LowerPattern INSTANCE = new LowerPattern();\n+\n+\t\tpublic final boolean matches(char c) {\n+\t\t\treturn Character.isLowerCase(c);\n+\t\t}\n+\t}\n+\n+\tprivate static final class UpperPattern implements CharacterPattern {\n+\t\tstatic final GroupHead.UpperPattern INSTANCE = new UpperPattern();\n+\n+\t\tpublic final boolean matches(char c) {\n+\t\t\treturn Character.isUpperCase(c);\n+\t\t}\n+\t}\n+\n+\tprivate static final class WhitespacePattern implements CharacterPattern {\n+\t\tstatic final GroupHead.WhitespacePattern INSTANCE = new WhitespacePattern();\n+\n+\t\tpublic final boolean matches(char c) {\n+\t\t\treturn Character.isWhitespace(c);\n+\t\t}\n+\t}\n+\n+\tprivate static final class OneCharacterPattern implements CharacterPattern {\n+\t\tprivate char expectedCharacter;\n+\n+\t\tOneCharacterPattern(final char c) {\n+\t\t\tthis.expectedCharacter = c;\n+\t\t}\n+\n+\t\tpublic final boolean matches(char c) {\n+\t\t\treturn this.expectedCharacter == c;\n+\t\t}\n+\t}\n+\n+\tprivate static final class PunctPattern implements CharacterPattern {\n+\t\tstatic final GroupHead.PunctPattern INSTANCE = new PunctPattern();\n+\n+\t\tprivate static String punctCharacters = \"-!\\\"#$%&'()*+,./:;<=>?@[\\\\]_`{|}~\";\n+\n+\t\tpublic boolean matches(char c) {\n+\t\t\treturn punctCharacters.indexOf(c) != -1;\n+\t\t}\n+\t}\n+\n+}\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/fnmatch/Head.java b/org.spearce.jgit/src/org/spearce/jgit/fnmatch/Head.java\nnew file mode 100644\nindex 0000000..498f96c\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/fnmatch/Head.java\n@@ -0,0 +1,50 @@\n+/*\n+ * Copyright (C) 2008, Florian KÃ¶berle <florianskarten@web.de>\n+ *\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or\n+ * without modification, are permitted provided that the following\n+ * conditions are met:\n+ *\n+ * - Redistributions of source code must retain the above copyright\n+ *   notice, this list of conditions and the following disclaimer.\n+ *\n+ * - Redistributions in binary form must reproduce the above\n+ *   copyright notice, this list of conditions and the following\n+ *   disclaimer in the documentation and/or other materials provided\n+ *   with the distribution.\n+ *\n+ * - Neither the name of the Git Development Community nor the\n+ *   names of its contributors may be used to endorse or promote\n+ *   products derived from this software without specific prior\n+ *   written permission.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n+ * CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+package org.spearce.jgit.fnmatch;\n+\n+import java.util.List;\n+\n+interface Head {\n+\t/**\n+\t * \n+\t * @param c\n+\t *            the character which decides which heads are returned.\n+\t * @return a list of heads based on the input.\n+\t */\n+\tpublic abstract List<Head> getNextHeads(char c);\n+}\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/fnmatch/LastHead.java b/org.spearce.jgit/src/org/spearce/jgit/fnmatch/LastHead.java\nnew file mode 100644\nindex 0000000..d3c9813\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/fnmatch/LastHead.java\n@@ -0,0 +1,56 @@\n+/*\n+ * Copyright (C) 2008, Florian KÃ¶berle <florianskarten@web.de>\n+ *\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or\n+ * without modification, are permitted provided that the following\n+ * conditions are met:\n+ *\n+ * - Redistributions of source code must retain the above copyright\n+ *   notice, this list of conditions and the following disclaimer.\n+ *\n+ * - Redistributions in binary form must reproduce the above\n+ *   copyright notice, this list of conditions and the following\n+ *   disclaimer in the documentation and/or other materials provided\n+ *   with the distribution.\n+ *\n+ * - Neither the name of the Git Development Community nor the\n+ *   names of its contributors may be used to endorse or promote\n+ *   products derived from this software without specific prior\n+ *   written permission.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n+ * CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+package org.spearce.jgit.fnmatch;\n+\n+import java.util.List;\n+\n+final class LastHead implements Head {\n+\tstatic final Head INSTANCE = new LastHead();\n+\n+\t/**\n+\t * Don't call this constructor, use {@link #INSTANCE}\n+\t */\n+\tprivate LastHead() {\n+\t\t// defined because of javadoc and visibility modifier.\n+\t}\n+\n+\tpublic List<Head> getNextHeads(char c) {\n+\t\treturn FileNameMatcher.EMPTY_HEAD_LIST;\n+\t}\n+\n+}\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/fnmatch/RestrictedWildCardHead.java b/org.spearce.jgit/src/org/spearce/jgit/fnmatch/RestrictedWildCardHead.java\nnew file mode 100644\nindex 0000000..9d8d277\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/fnmatch/RestrictedWildCardHead.java\n@@ -0,0 +1,52 @@\n+/*\n+ * Copyright (C) 2008, Florian KÃ¶berle <florianskarten@web.de>\n+ *\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or\n+ * without modification, are permitted provided that the following\n+ * conditions are met:\n+ *\n+ * - Redistributions of source code must retain the above copyright\n+ *   notice, this list of conditions and the following disclaimer.\n+ *\n+ * - Redistributions in binary form must reproduce the above\n+ *   copyright notice, this list of conditions and the following\n+ *   disclaimer in the documentation and/or other materials provided\n+ *   with the distribution.\n+ *\n+ * - Neither the name of the Git Development Community nor the\n+ *   names of its contributors may be used to endorse or promote\n+ *   products derived from this software without specific prior\n+ *   written permission.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n+ * CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+package org.spearce.jgit.fnmatch;\n+\n+final class RestrictedWildCardHead extends AbstractHead {\n+\tprivate final char excludedCharacter;\n+\n+\tRestrictedWildCardHead(final char excludedCharacter, final boolean star) {\n+\t\tsuper(star);\n+\t\tthis.excludedCharacter = excludedCharacter;\n+\t}\n+\n+\t@Override\n+\tprotected final boolean matches(final char c) {\n+\t\treturn c != excludedCharacter;\n+\t}\n+}\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/fnmatch/WildCardHead.java b/org.spearce.jgit/src/org/spearce/jgit/fnmatch/WildCardHead.java\nnew file mode 100644\nindex 0000000..570e374\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/fnmatch/WildCardHead.java\n@@ -0,0 +1,49 @@\n+/*\n+ * Copyright (C) 2008, Florian KÃ¶berle <florianskarten@web.de>\n+ *\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or\n+ * without modification, are permitted provided that the following\n+ * conditions are met:\n+ *\n+ * - Redistributions of source code must retain the above copyright\n+ *   notice, this list of conditions and the following disclaimer.\n+ *\n+ * - Redistributions in binary form must reproduce the above\n+ *   copyright notice, this list of conditions and the following\n+ *   disclaimer in the documentation and/or other materials provided\n+ *   with the distribution.\n+ *\n+ * - Neither the name of the Git Development Community nor the\n+ *   names of its contributors may be used to endorse or promote\n+ *   products derived from this software without specific prior\n+ *   written permission.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n+ * CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+package org.spearce.jgit.fnmatch;\n+\n+final class WildCardHead extends AbstractHead {\n+\tWildCardHead(boolean star) {\n+\t\tsuper(star);\n+\t}\n+\n+\t@Override\n+\tprotected final boolean matches(final char c) {\n+\t\treturn true;\n+\t}\n+}\n-- \n1.5.4.3\n"},{"id":"79749","messageId":"1213382121-19786-2-git-send-email-florianskarten@web.de","threadId":"13934","inReplyTo":"4852BCCA.4030404@web.de","subject":"[JGIT PATCH v4 02/24] Added the interface FilePattern.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-06-13T18:34:59Z","receivedAt":"2008-06-13T18:34:59Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Signed-off-by: Florian Koeberle <florianskarten@web.de>\n---\n .../spearce/jgit/treewalk/rules/FilePattern.java   |  128 ++++++++++++++++++++\n 1 files changed, 128 insertions(+), 0 deletions(-)\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/FilePattern.java\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/FilePattern.java b/org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/FilePattern.java\nnew file mode 100644\nindex 0000000..86cba6b\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/FilePattern.java\n@@ -0,0 +1,128 @@\n+/*\n+ * Copyright (C) 2008, Florian KÃ¶berle <florianskarten@web.de>\n+ *\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or\n+ * without modification, are permitted provided that the following\n+ * conditions are met:\n+ *\n+ * - Redistributions of source code must retain the above copyright\n+ *   notice, this list of conditions and the following disclaimer.\n+ *\n+ * - Redistributions in binary form must reproduce the above\n+ *   copyright notice, this list of conditions and the following\n+ *   disclaimer in the documentation and/or other materials provided\n+ *   with the distribution.\n+ *\n+ * - Neither the name of the Git Development Community nor the\n+ *   names of its contributors may be used to endorse or promote\n+ *   products derived from this software without specific prior\n+ *   written permission.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n+ * CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+package org.spearce.jgit.treewalk.rules;\n+\n+/**\n+ * A {@link FilePattern} can be used to check if files in a directory matches a\n+ * pattern. It provides with the {@link #getPatternForSubDirectory(String)}\n+ * method {@link FilePattern}s for sub directories.\n+ * \n+ * Implementations of this interface should be immutable.\n+ * \n+ */\n+interface FilePattern {\n+\t/**\n+\t * Contains the only instance of {@link FilePatternMatchAlways}.\n+\t */\n+\tpublic static final FilePattern MATCH_ALWAYS = new FilePatternMatchAlways();\n+\n+\t/**\n+\t * Contains the only instance of {@link FilePatternMatchNever}.\n+\t */\n+\tpublic static final FilePattern MATCH_NEVER = new FilePatternMatchNever();\n+\n+\t/**\n+\t * @param fileName\n+\t *            the name of the file or directory\n+\t * @param fileIsDirectory\n+\t *            determines if the file is a directory.\n+\t * @return true if the pattern matches.\n+\t */\n+\tboolean match(String fileName, boolean fileIsDirectory);\n+\n+\t/**\n+\t * \n+\t * @param directoryName\n+\t *            the name of a subdirectory.\n+\t * @return a pattern which can be used to match files in sub directories. A\n+\t *         user may check if the returned value is {@link #MATCH_NEVER} in\n+\t *         order to do some performance optimizations.\n+\t * \n+\t */\n+\tFilePattern getPatternForSubDirectory(String directoryName);\n+\n+\t/**\n+\t * @return true if {@link #getPatternForSubDirectory(String)} returns true\n+\t *         for every value.\n+\t */\n+\tboolean isSameForSubDirectories();\n+\n+\t/**\n+\t * This implementation does always match.\n+\t */\n+\tpublic static final class FilePatternMatchAlways implements FilePattern {\n+\n+\t\tprivate FilePatternMatchAlways() {\n+\t\t\t// declared to make the constructor private\n+\t\t}\n+\n+\t\tpublic FilePattern getPatternForSubDirectory(String directoryName) {\n+\t\t\treturn MATCH_ALWAYS;\n+\t\t}\n+\n+\t\tpublic boolean match(String fileName, boolean fileIsDirectory) {\n+\t\t\treturn true;\n+\t\t}\n+\n+\t\tpublic boolean isSameForSubDirectories() {\n+\t\t\treturn true;\n+\t\t}\n+\t}\n+\n+\t/**\n+\t * This implementation does never match.\n+\t */\n+\tpublic static final class FilePatternMatchNever implements FilePattern {\n+\t\tprivate FilePatternMatchNever() {\n+\t\t\t// declared to make the constructor private\n+\t\t}\n+\n+\t\tpublic FilePattern getPatternForSubDirectory(String directoryName) {\n+\t\t\treturn MATCH_NEVER;\n+\t\t}\n+\n+\t\tpublic boolean match(String fileName, boolean fileIsDirectory) {\n+\t\t\treturn false;\n+\t\t}\n+\n+\t\tpublic boolean isSameForSubDirectories() {\n+\t\t\treturn true;\n+\t\t}\n+\t}\n+\n+}\n-- \n1.5.4.3\n"},{"id":"79750","messageId":"1213382121-19786-3-git-send-email-florianskarten@web.de","threadId":"13934","inReplyTo":"4852BCCA.4030404@web.de","subject":"[JGIT PATCH v4 03/24] Added the class Rule.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-06-13T18:35:00Z","receivedAt":"2008-06-13T18:35:00Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Signed-off-by: Florian Koeberle <florianskarten@web.de>\n---\n .../src/org/spearce/jgit/treewalk/rules/Rule.java  |   82 ++++++++++++++++++++\n 1 files changed, 82 insertions(+), 0 deletions(-)\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/Rule.java\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/Rule.java b/org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/Rule.java\nnew file mode 100644\nindex 0000000..8e5b2f4\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/Rule.java\n@@ -0,0 +1,82 @@\n+/*\n+ * Copyright (C) 2008, Florian KÃ¶berle <florianskarten@web.de>\n+ *\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or\n+ * without modification, are permitted provided that the following\n+ * conditions are met:\n+ *\n+ * - Redistributions of source code must retain the above copyright\n+ *   notice, this list of conditions and the following disclaimer.\n+ *\n+ * - Redistributions in binary form must reproduce the above\n+ *   copyright notice, this list of conditions and the following\n+ *   disclaimer in the documentation and/or other materials provided\n+ *   with the distribution.\n+ *\n+ * - Neither the name of the Git Development Community nor the\n+ *   names of its contributors may be used to endorse or promote\n+ *   products derived from this software without specific prior\n+ *   written permission.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n+ * CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+package org.spearce.jgit.treewalk.rules;\n+\n+/**\n+ * A Rule defines what to do with a files which match a specified\n+ * {@link FilePattern}.\n+ */\n+public class Rule {\n+\tprivate boolean ignoreAtMatch;\n+\n+\tprivate FilePattern pattern;\n+\n+\t/**\n+\t * \n+\t * @param ignoreAtMatch\n+\t *            defines if the rules ignores or accepts at a match.\n+\t * @param pattern\n+\t *            the pattern used to test if a file matches.\n+\t */\n+\tRule(boolean ignoreAtMatch, FilePattern pattern) {\n+\t\tthis.ignoreAtMatch = ignoreAtMatch;\n+\t\tthis.pattern = pattern;\n+\t}\n+\n+\tFilePattern getPattern() {\n+\t\treturn pattern;\n+\t}\n+\n+\tboolean isIgnoreAtMatch() {\n+\t\treturn ignoreAtMatch;\n+\t}\n+\n+\tRule getRuleForSubDirectory(String directoryName) {\n+\t\tfinal FilePattern subPattern = pattern\n+\t\t\t\t.getPatternForSubDirectory(directoryName);\n+\t\tif (subPattern == pattern) {\n+\t\t\treturn this;\n+\t\t}\n+\t\treturn new Rule(ignoreAtMatch, subPattern);\n+\t}\n+\n+\tboolean isSameForSubDirectories() {\n+\t\treturn pattern.isSameForSubDirectories();\n+\t}\n+\n+}\n-- \n1.5.4.3\n"},{"id":"79758","messageId":"1213382121-19786-4-git-send-email-florianskarten@web.de","threadId":"13934","inReplyTo":"4852BCCA.4030404@web.de","subject":"[JGIT PATCH v4 04/24] Added the iterface Rules.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-06-13T18:35:01Z","receivedAt":"2008-06-13T18:35:01Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Signed-off-by: Florian Koeberle <florianskarten@web.de>\n---\n .../src/org/spearce/jgit/treewalk/rules/Rules.java |  121 ++++++++++++++++++++\n 1 files changed, 121 insertions(+), 0 deletions(-)\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/Rules.java\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/Rules.java b/org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/Rules.java\nnew file mode 100644\nindex 0000000..0a71150\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/Rules.java\n@@ -0,0 +1,121 @@\n+/*\n+ * Copyright (C) 2008, Florian KÃ¶berle <florianskarten@web.de>\n+ *\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or\n+ * without modification, are permitted provided that the following\n+ * conditions are met:\n+ *\n+ * - Redistributions of source code must retain the above copyright\n+ *   notice, this list of conditions and the following disclaimer.\n+ *\n+ * - Redistributions in binary form must reproduce the above\n+ *   copyright notice, this list of conditions and the following\n+ *   disclaimer in the documentation and/or other materials provided\n+ *   with the distribution.\n+ *\n+ * - Neither the name of the Git Development Community nor the\n+ *   names of its contributors may be used to endorse or promote\n+ *   products derived from this software without specific prior\n+ *   written permission.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n+ * CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+package org.spearce.jgit.treewalk.rules;\n+\n+/**\n+ * A {@link Rules} instances defines ignore or do not ignore rules for files in\n+ * a directory. It can't directly be used to match files in sub directories, but\n+ * provides a method {@link #getRulesForSubDirectory}.\n+ * \n+ */\n+public interface Rules {\n+\n+\t/**\n+\t * Provides the instance of {@link IgnoreAllRules}.\n+\t */\n+\tpublic static final Rules IGNORE_ALL = new IgnoreAllRules();\n+\n+\t/**\n+\t * Provides the instance of {@link IgnoreNothingRules}.\n+\t */\n+\tpublic static final Rules IGNORE_NOTHING = new IgnoreNothingRules();\n+\n+\t/**\n+\t * @param fileName\n+\t *            the name of the file or directory.\n+\t * @param fileIsDirectory\n+\t *            should be true if the file is a directory.\n+\t * @return true if the file or directory should be ignored.\n+\t */\n+\tpublic abstract boolean shouldIgnore(String fileName,\n+\t\t\tboolean fileIsDirectory);\n+\n+\t/**\n+\t * @param directoryName\n+\t *            the sub directory for which you want an {@link Rules}\n+\t *            instance.\n+\t * @return an {@link Rules} instance, which can be used to check files in\n+\t *         the specified sub directory.\n+\t */\n+\tpublic abstract Rules getRulesForSubDirectory(String directoryName);\n+\n+\t/**\n+\t * This implementation ignores everything.\n+\t */\n+\tpublic static final class IgnoreAllRules implements Rules {\n+\t\tprivate IgnoreAllRules() {\n+\t\t\t// declared to make the constructor private\n+\t\t}\n+\n+\t\tpublic Rules getRulesForSubDirectory(String directoryName) {\n+\t\t\treturn this;\n+\t\t}\n+\n+\t\tpublic boolean shouldIgnore(String fileName, boolean fileIsDirectory) {\n+\t\t\treturn true;\n+\t\t}\n+\n+\t\t@Override\n+\t\tpublic String toString() {\n+\t\t\treturn \"Rules[IGNORE_ALL]\";\n+\t\t}\n+\t}\n+\n+\t/**\n+\t * This implementation ignores nothing.\n+\t */\n+\tpublic static final class IgnoreNothingRules implements Rules {\n+\t\tprivate IgnoreNothingRules() {\n+\t\t\t// declared to make the constructor private\n+\t\t}\n+\n+\t\tpublic Rules getRulesForSubDirectory(String directoryName) {\n+\t\t\treturn this;\n+\t\t}\n+\n+\t\tpublic boolean shouldIgnore(String fileName, boolean fileIsDirectory) {\n+\t\t\treturn false;\n+\t\t}\n+\n+\t\t@Override\n+\t\tpublic String toString() {\n+\t\t\treturn \"Rules[IGNORE_NOTHING]\";\n+\t\t}\n+\t}\n+\n+}\n-- \n1.5.4.3\n"},{"id":"79760","messageId":"1213382121-19786-5-git-send-email-florianskarten@web.de","threadId":"13934","inReplyTo":"4852BCCA.4030404@web.de","subject":"[JGIT PATCH v4 05/24] Added the class FileNamePattern.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-06-13T18:35:02Z","receivedAt":"2008-06-13T18:35:02Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Signed-off-by: Florian Koeberle <florianskarten@web.de>\n---\n .../jgit/treewalk/rules/FileNamePattern.java       |   79 ++++++++++++++++++++\n 1 files changed, 79 insertions(+), 0 deletions(-)\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/FileNamePattern.java\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/FileNamePattern.java b/org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/FileNamePattern.java\nnew file mode 100644\nindex 0000000..3760308\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/FileNamePattern.java\n@@ -0,0 +1,79 @@\n+/*\n+ * Copyright (C) 2008, Florian KÃ¶berle <florianskarten@web.de>\n+ *\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or\n+ * without modification, are permitted provided that the following\n+ * conditions are met:\n+ *\n+ * - Redistributions of source code must retain the above copyright\n+ *   notice, this list of conditions and the following disclaimer.\n+ *\n+ * - Redistributions in binary form must reproduce the above\n+ *   copyright notice, this list of conditions and the following\n+ *   disclaimer in the documentation and/or other materials provided\n+ *   with the distribution.\n+ *\n+ * - Neither the name of the Git Development Community nor the\n+ *   names of its contributors may be used to endorse or promote\n+ *   products derived from this software without specific prior\n+ *   written permission.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n+ * CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+package org.spearce.jgit.treewalk.rules;\n+\n+import org.spearce.jgit.errors.InvalidPatternException;\n+import org.spearce.jgit.fnmatch.FileNameMatcher;\n+\n+/**\n+ * A {@link FileNamePattern} defines a pattern for all files in a tree. A\n+ * typical example would be \"*.txt\", which would match at any file or subtree\n+ * which ends with \".txt\" like \"a/b/c.txt\" and \"a.txt/a.c\".\n+ * \n+ */\n+class FileNamePattern implements FilePattern {\n+\tprivate final FileNameMatcher fileNameMatcher;\n+\n+\tprivate final boolean matchDirectoriesOnly;\n+\n+\tFileNamePattern(String fnMatchPatternString, boolean matchDirectoriesOnly)\n+\t\t\tthrows InvalidPatternException {\n+\t\tthis.fileNameMatcher = new FileNameMatcher(fnMatchPatternString, null);\n+\t\tthis.matchDirectoriesOnly = matchDirectoriesOnly;\n+\t}\n+\n+\tpublic FilePattern getPatternForSubDirectory(String directoryName) {\n+\t\tif (match(directoryName, true)) {\n+\t\t\treturn MATCH_ALWAYS;\n+\t\t}\n+\t\treturn this;\n+\t}\n+\n+\tpublic boolean match(String fileName, boolean fileIsDirectory) {\n+\t\tif (matchDirectoriesOnly && !fileIsDirectory)\n+\t\t\treturn false;\n+\n+\t\tfileNameMatcher.reset();\n+\t\tfileNameMatcher.append(fileName);\n+\t\treturn fileNameMatcher.isMatch();\n+\t}\n+\n+\tpublic boolean isSameForSubDirectories() {\n+\t\treturn false;\n+\t}\n+}\n-- \n1.5.4.3\n"},{"id":"79759","messageId":"1213382121-19786-6-git-send-email-florianskarten@web.de","threadId":"13934","inReplyTo":"4852BCCA.4030404@web.de","subject":"[JGIT PATCH v4 06/24] Added the class FilePathPattern.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-06-13T18:35:03Z","receivedAt":"2008-06-13T18:35:03Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Signed-off-by: Florian Koeberle <florianskarten@web.de>\n---\n .../jgit/treewalk/rules/FilePathPattern.java       |   97 ++++++++++++++++++++\n 1 files changed, 97 insertions(+), 0 deletions(-)\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/FilePathPattern.java\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/FilePathPattern.java b/org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/FilePathPattern.java\nnew file mode 100644\nindex 0000000..cd7c9aa\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/FilePathPattern.java\n@@ -0,0 +1,97 @@\n+/*\n+ * Copyright (C) 2008, Florian KÃ¶berle <florianskarten@web.de>\n+ *\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or\n+ * without modification, are permitted provided that the following\n+ * conditions are met:\n+ *\n+ * - Redistributions of source code must retain the above copyright\n+ *   notice, this list of conditions and the following disclaimer.\n+ *\n+ * - Redistributions in binary form must reproduce the above\n+ *   copyright notice, this list of conditions and the following\n+ *   disclaimer in the documentation and/or other materials provided\n+ *   with the distribution.\n+ *\n+ * - Neither the name of the Git Development Community nor the\n+ *   names of its contributors may be used to endorse or promote\n+ *   products derived from this software without specific prior\n+ *   written permission.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n+ * CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+package org.spearce.jgit.treewalk.rules;\n+\n+import org.spearce.jgit.errors.InvalidPatternException;\n+import org.spearce.jgit.fnmatch.FileNameMatcher;\n+\n+/**\n+ * A {@link FilePathPattern} represents a pattern for a file path.\n+ * \n+ */\n+class FilePathPattern implements FilePattern {\n+\tprivate final FileNameMatcher matcher;\n+\n+\tprivate final boolean matchDirectoriesOnly;\n+\n+\tprivate FilePathPattern(final FileNameMatcher matcher,\n+\t\t\tfinal boolean matchDirectoriesOnly) {\n+\t\tthis.matcher = matcher;\n+\t\tthis.matchDirectoriesOnly = matchDirectoriesOnly;\n+\t}\n+\n+\tFilePathPattern(final String pattern, final boolean allowSlashInWildCard,\n+\t\t\tfinal boolean matchDirectoriesOnly) throws InvalidPatternException {\n+\n+\t\tif (allowSlashInWildCard)\n+\t\t\tthis.matcher = new FileNameMatcher(pattern, null);\n+\t\telse\n+\t\t\tthis.matcher = new FileNameMatcher(pattern, new Character('/'));\n+\t\tthis.matchDirectoriesOnly = matchDirectoriesOnly;\n+\t}\n+\n+\tpublic FilePattern getPatternForSubDirectory(String directoryName) {\n+\t\tmatcher.reset();\n+\t\tmatcher.append(directoryName);\n+\n+\t\tif (matcher.isMatch())\n+\t\t\treturn FilePattern.MATCH_ALWAYS;\n+\n+\t\tmatcher.append(\"/\");\n+\n+\t\tif (!matcher.canAppendMatch())\n+\t\t\treturn FilePattern.MATCH_NEVER;\n+\n+\t\tfinal FileNameMatcher childMatcher = matcher.createMatcherForSuffix();\n+\t\treturn new FilePathPattern(childMatcher, matchDirectoriesOnly);\n+\t}\n+\n+\tpublic boolean match(String fileName, boolean fileIsDirectory) {\n+\t\tif (!fileIsDirectory && matchDirectoriesOnly) {\n+\t\t\treturn false;\n+\t\t}\n+\t\tmatcher.reset();\n+\t\tmatcher.append(fileName);\n+\t\treturn matcher.isMatch();\n+\t}\n+\n+\tpublic boolean isSameForSubDirectories() {\n+\t\treturn false;\n+\t}\n+\n+}\n-- \n1.5.4.3\n"},{"id":"79752","messageId":"1213382121-19786-7-git-send-email-florianskarten@web.de","threadId":"13934","inReplyTo":"4852BCCA.4030404@web.de","subject":"[JGIT PATCH v4 07/24] Added the class IgnoreRuleListFactory.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-06-13T18:35:04Z","receivedAt":"2008-06-13T18:35:04Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Signed-off-by: Florian Koeberle <florianskarten@web.de>\n---\n .../jgit/treewalk/rules/IgnoreRuleListFactory.java |  115 ++++++++++++++++++++\n 1 files changed, 115 insertions(+), 0 deletions(-)\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/IgnoreRuleListFactory.java\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/IgnoreRuleListFactory.java b/org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/IgnoreRuleListFactory.java\nnew file mode 100644\nindex 0000000..aa4a384\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/IgnoreRuleListFactory.java\n@@ -0,0 +1,115 @@\n+/*\n+ * Copyright (C) 2008, Florian KÃ¶berle <florianskarten@web.de>\n+ *\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or\n+ * without modification, are permitted provided that the following\n+ * conditions are met:\n+ *\n+ * - Redistributions of source code must retain the above copyright\n+ *   notice, this list of conditions and the following disclaimer.\n+ *\n+ * - Redistributions in binary form must reproduce the above\n+ *   copyright notice, this list of conditions and the following\n+ *   disclaimer in the documentation and/or other materials provided\n+ *   with the distribution.\n+ *\n+ * - Neither the name of the Git Development Community nor the\n+ *   names of its contributors may be used to endorse or promote\n+ *   products derived from this software without specific prior\n+ *   written permission.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n+ * CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+package org.spearce.jgit.treewalk.rules;\n+\n+import java.io.File;\n+import java.io.FileNotFoundException;\n+import java.util.ArrayList;\n+import java.util.LinkedList;\n+import java.util.List;\n+import java.util.Scanner;\n+\n+import org.spearce.jgit.errors.InvalidPatternException;\n+\n+/**\n+ * This class can be used to create lists of {@link Rule} objects from lines of\n+ * .gitignore like files.\n+ * \n+ */\n+class IgnoreRuleListFactory {\n+\n+\tList<Rule> createIgnoreRuleList(final Iterable<String> lineIterable)\n+\t\t\tthrows InvalidPatternException {\n+\t\tLinkedList<Rule> rules = new LinkedList<Rule>();\n+\t\tfor (String line : lineIterable) {\n+\t\t\tfinal String trimmedLine = line.trim();\n+\t\t\tif (trimmedLine.startsWith(\"#\")) {\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t\tif (trimmedLine.length() == 0) {\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t\trules.add(0, createRule(trimmedLine));\n+\t\t}\n+\t\treturn rules;\n+\t}\n+\n+\tList<Rule> createIgnoreRuleList(final List<File> files)\n+\t\t\tthrows FileNotFoundException, InvalidPatternException {\n+\t\tfinal List<String> lines = new ArrayList<String>();\n+\t\tfor (File file : files) {\n+\t\t\tScanner scanner = new Scanner(file);\n+\t\t\ttry {\n+\t\t\t\twhile (scanner.hasNextLine()) {\n+\t\t\t\t\tlines.add(scanner.nextLine());\n+\t\t\t\t}\n+\t\t\t} finally {\n+\t\t\t\tscanner.close();\n+\t\t\t}\n+\t\t}\n+\t\treturn createIgnoreRuleList(lines);\n+\t}\n+\n+\tprivate Rule createRule(String patternString)\n+\t\t\tthrows InvalidPatternException {\n+\t\tfinal boolean inverse = patternString.startsWith(\"!\");\n+\t\tif (inverse)\n+\t\t\tpatternString = patternString.substring(1);\n+\n+\t\tfinal FilePattern pattern = createFilePattern(patternString);\n+\t\treturn new Rule(!inverse, pattern);\n+\t}\n+\n+\tprivate FilePattern createFilePattern(String patternString)\n+\t\t\tthrows InvalidPatternException {\n+\t\tfinal boolean matchDirectoriesOnly = patternString.endsWith(\"/\");\n+\t\tif (matchDirectoriesOnly)\n+\t\t\tpatternString = patternString.substring(0,\n+\t\t\t\t\tpatternString.length() - 1);\n+\t\tif (patternString.contains(\"/\")) {\n+\t\t\tif (patternString.startsWith(\"/\"))\n+\t\t\t\tpatternString = patternString.substring(1);\n+\n+\t\t\treturn new FilePathPattern(patternString, false,\n+\t\t\t\t\tmatchDirectoriesOnly);\n+\t\t} else {\n+\t\t\treturn new FileNamePattern(patternString, matchDirectoriesOnly);\n+\t\t}\n+\t}\n+\n+}\n-- \n1.5.4.3\n"},{"id":"79756","messageId":"1213382121-19786-8-git-send-email-florianskarten@web.de","threadId":"13934","inReplyTo":"4852BCCA.4030404@web.de","subject":"[JGIT PATCH v4 08/24] Added a Rules interface implementation and a factory for it.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-06-13T18:35:05Z","receivedAt":"2008-06-13T18:35:05Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Signed-off-by: Florian Koeberle <florianskarten@web.de>\n---\n .../treewalk/rules/RuleListToObjectConverter.java  |  151 ++++++++++++++++++++\n .../jgit/treewalk/rules/RulesImplementation.java   |   88 ++++++++++++\n 2 files changed, 239 insertions(+), 0 deletions(-)\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/RuleListToObjectConverter.java\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/RulesImplementation.java\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/RuleListToObjectConverter.java b/org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/RuleListToObjectConverter.java\nnew file mode 100644\nindex 0000000..96f27bb\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/RuleListToObjectConverter.java\n@@ -0,0 +1,151 @@\n+/*\n+ * Copyright (C) 2008, Florian KÃ¶berle <florianskarten@web.de>\n+ *\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or\n+ * without modification, are permitted provided that the following\n+ * conditions are met:\n+ *\n+ * - Redistributions of source code must retain the above copyright\n+ *   notice, this list of conditions and the following disclaimer.\n+ *\n+ * - Redistributions in binary form must reproduce the above\n+ *   copyright notice, this list of conditions and the following\n+ *   disclaimer in the documentation and/or other materials provided\n+ *   with the distribution.\n+ *\n+ * - Neither the name of the Git Development Community nor the\n+ *   names of its contributors may be used to endorse or promote\n+ *   products derived from this software without specific prior\n+ *   written permission.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n+ * CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+package org.spearce.jgit.treewalk.rules;\n+\n+import java.util.ArrayList;\n+import java.util.Iterator;\n+import java.util.List;\n+\n+/**\n+ * This class converts a list of {@link Rule} objects into a {@Rules} object.\n+ * During the conversion some optimizations are done:\n+ * <ul>\n+ * <li>Rules which can never match are removed. e.g. There is no need to check\n+ * the rule \"/a\" in the directory b.</li>\n+ * <li>The list is cut at the first rule which match always. *.txt\\n/a for\n+ * example would result in an internal list \"ignore all, ignore *.txt\" which is\n+ * then reduced to \"ignore all\".</li>\n+ * <li>Ignore rules which are direcly before an \"ignore all\" all rule are\n+ * removed. /a\\n*.txt for example would result in an intern \"ignore *.txt,\n+ * ignore all\" list which is then reduced to \"ignore all\",</li>\n+ * <li>\"do not ignore\" rules at the bottom of the intern list are removed. This\n+ * optimization would remove !a from \"!a\\n/b\" as it is in the inversed list at\n+ * the bottom.</li>\n+ * </ul>\n+ */\n+class RuleListToObjectConverter {\n+\tprotected Rules createIgnoreRules(Iterator<Rule> ruleIterator) {\n+\t\tfinal List<Rule> rules = getNessesaryRulesFromIterator(ruleIterator);\n+\t\tremoveUnnecessaryDoNotIgnoreRulesAtTheEndOfTheList(rules);\n+\t\tremoveUnnecessaryIgnoreRulesNearTheEndOfTheList(rules);\n+\n+\t\tif (rules.size() == 1) {\n+\t\t\tfinal Rule rule = rules.get(0);\n+\t\t\tif (rule.getPattern() == FilePattern.MATCH_ALWAYS) {\n+\t\t\t\tif (rule.isIgnoreAtMatch()) {\n+\t\t\t\t\treturn Rules.IGNORE_ALL;\n+\t\t\t\t} else {\n+\t\t\t\t\treturn Rules.IGNORE_NOTHING;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t} else if (rules.isEmpty()) {\n+\t\t\treturn Rules.IGNORE_NOTHING;\n+\t\t}\n+\t\treturn new RulesImplementation(rules, this);\n+\t}\n+\n+\tprivate List<Rule> getNessesaryRulesFromIterator(Iterator<Rule> ruleIterator) {\n+\t\tfinal List<Rule> rules = new ArrayList<Rule>();\n+\t\twhile (ruleIterator.hasNext()) {\n+\t\t\tfinal Rule subRule = ruleIterator.next();\n+\t\t\tif (subRule.getPattern() == FilePattern.MATCH_NEVER) {\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t\trules.add(subRule);\n+\t\t\t// There is no need for rules after a rule witch match always,\n+\t\t\t// as such a rule would never be the first rule which matches.\n+\t\t\tif (subRule.getPattern() == FilePattern.MATCH_ALWAYS) {\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\t\treturn rules;\n+\t}\n+\n+\t/**\n+\t * Expects that\n+\t * {@link #removeUnnecessaryDoNotIgnoreRulesAtTheEndOfTheList(List)} has\n+\t * been executed first.\n+\t * \n+\t * @param rules\n+\t *            rule list to reduce.\n+\t */\n+\tprivate void removeUnnecessaryIgnoreRulesNearTheEndOfTheList(\n+\t\t\tfinal List<Rule> rules) {\n+\t\t// Why the following optimization makes only sense for the end of the\n+\t\t// list:\n+\t\t// If there is a \"ignore all\"- rule,\n+\t\t// then it is located at the end of the list\n+\t\t// See how the list is filled to prove this statement.\n+\t\tif (rules.size() >= 2) {\n+\t\t\tfinal Rule lastRule = rules.get(rules.size() - 1);\n+\t\t\tassert lastRule.isIgnoreAtMatch() : \"Expected that no 'not ignore'-rule is at the end of the list any more\";\n+\t\t\tfinal boolean ignoreAllAtEnd = lastRule.getPattern().equals(\n+\t\t\t\t\tFilePattern.MATCH_ALWAYS);\n+\t\t\tif (ignoreAllAtEnd) {\n+\t\t\t\twhile (rules.size() >= 2) {\n+\t\t\t\t\tfinal int ruleBeforeLastIndex = rules.size() - 2;\n+\t\t\t\t\tfinal Rule ruleBeforeLast = rules.get(ruleBeforeLastIndex);\n+\t\t\t\t\tif (ruleBeforeLast.isIgnoreAtMatch()) {\n+\t\t\t\t\t\trules.remove(ruleBeforeLastIndex);\n+\t\t\t\t\t} else {\n+\t\t\t\t\t\tbreak;\n+\t\t\t\t\t}\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\tprivate void removeUnnecessaryDoNotIgnoreRulesAtTheEndOfTheList(\n+\t\t\tfinal List<Rule> rules) {\n+\t\t// Why it is save to remove \"don't ignore rules\" at the end of the list\n+\t\t// if there is no \"ignore rule\" below a \"don't ignore rule\" then\n+\t\t// the path which haven't match jet will never be ignored:\n+\t\t// -> if another \"don't ignore rule\" match then the patch will not be\n+\t\t// ignored\n+\t\t// -> if no \"don't ignore rule\" match then the path will not be ignored.\n+\t\twhile (!rules.isEmpty()) {\n+\t\t\tfinal int indexOfLastRule = rules.size() - 1;\n+\t\t\tfinal Rule lastRule = rules.get(indexOfLastRule);\n+\t\t\tif (lastRule.isIgnoreAtMatch()) {\n+\t\t\t\tbreak;\n+\t\t\t} else {\n+\t\t\t\trules.remove(indexOfLastRule);\n+\t\t\t}\n+\t\t}\n+\t}\n+}\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/RulesImplementation.java b/org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/RulesImplementation.java\nnew file mode 100644\nindex 0000000..cd12701\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/RulesImplementation.java\n@@ -0,0 +1,88 @@\n+/*\n+ * Copyright (C) 2008, Florian KÃ¶berle <florianskarten@web.de>\n+ *\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or\n+ * without modification, are permitted provided that the following\n+ * conditions are met:\n+ *\n+ * - Redistributions of source code must retain the above copyright\n+ *   notice, this list of conditions and the following disclaimer.\n+ *\n+ * - Redistributions in binary form must reproduce the above\n+ *   copyright notice, this list of conditions and the following\n+ *   disclaimer in the documentation and/or other materials provided\n+ *   with the distribution.\n+ *\n+ * - Neither the name of the Git Development Community nor the\n+ *   names of its contributors may be used to endorse or promote\n+ *   products derived from this software without specific prior\n+ *   written permission.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n+ * CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+package org.spearce.jgit.treewalk.rules;\n+\n+import java.util.Iterator;\n+import java.util.List;\n+\n+class RulesImplementation implements Rules {\n+\t/**\n+\t * Complete list of rules. Note that order is: determining rule first.\n+\t */\n+\tprivate final List<Rule> rules;\n+\n+\t/**\n+\t * Factory used to create {@link Rules} for sub directories.\n+\t */\n+\tprivate RuleListToObjectConverter factory;\n+\n+\tRulesImplementation(List<Rule> rules, RuleListToObjectConverter factory) {\n+\t\tthis.rules = rules;\n+\t\tthis.factory = factory;\n+\t}\n+\n+\tpublic boolean shouldIgnore(String fileName, boolean fileIsDirectory) {\n+\t\tfor (Rule rule : rules) {\n+\t\t\tif (rule.getPattern().match(fileName, fileIsDirectory)) {\n+\t\t\t\treturn rule.isIgnoreAtMatch();\n+\t\t\t}\n+\t\t}\n+\t\treturn false;\n+\t}\n+\n+\tpublic Rules getRulesForSubDirectory(final String directoryName) {\n+\t\tfinal Iterator<Rule> subRuleIterator = new Iterator<Rule>() {\n+\t\t\tfinal Iterator<Rule> ruleIterator = rules.iterator();\n+\n+\t\t\tpublic boolean hasNext() {\n+\t\t\t\treturn ruleIterator.hasNext();\n+\t\t\t}\n+\n+\t\t\tpublic Rule next() {\n+\t\t\t\treturn ruleIterator.next()\n+\t\t\t\t\t\t.getRuleForSubDirectory(directoryName);\n+\t\t\t}\n+\n+\t\t\tpublic void remove() {\n+\t\t\t\tthrow new UnsupportedOperationException();\n+\t\t\t}\n+\n+\t\t};\n+\t\treturn factory.createIgnoreRules(subRuleIterator);\n+\t}\n+}\n-- \n1.5.4.3\n"},{"id":"79754","messageId":"1213382121-19786-9-git-send-email-florianskarten@web.de","threadId":"13934","inReplyTo":"4852BCCA.4030404@web.de","subject":"[JGIT PATCH v4 09/24] Added test class OverallIgnoreRulestest.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-06-13T18:35:06Z","receivedAt":"2008-06-13T18:35:06Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Signed-off-by: Florian Koeberle <florianskarten@web.de>\n---\n .../treewalk/rules/OverallIgnoreRulesTest.java     |  396 ++++++++++++++++++++\n 1 files changed, 396 insertions(+), 0 deletions(-)\n create mode 100644 org.spearce.jgit.test/tst/org/spearce/jgit/treewalk/rules/OverallIgnoreRulesTest.java\n\ndiff --git a/org.spearce.jgit.test/tst/org/spearce/jgit/treewalk/rules/OverallIgnoreRulesTest.java b/org.spearce.jgit.test/tst/org/spearce/jgit/treewalk/rules/OverallIgnoreRulesTest.java\nnew file mode 100644\nindex 0000000..55e9de5\n--- /dev/null\n+++ b/org.spearce.jgit.test/tst/org/spearce/jgit/treewalk/rules/OverallIgnoreRulesTest.java\n@@ -0,0 +1,396 @@\n+/*\n+ * Copyright (C) 2008, Florian KÃ¶berle <florianskarten@web.de>\n+ *\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or\n+ * without modification, are permitted provided that the following\n+ * conditions are met:\n+ *\n+ * - Redistributions of source code must retain the above copyright\n+ *   notice, this list of conditions and the following disclaimer.\n+ *\n+ * - Redistributions in binary form must reproduce the above\n+ *   copyright notice, this list of conditions and the following\n+ *   disclaimer in the documentation and/or other materials provided\n+ *   with the distribution.\n+ *\n+ * - Neither the name of the Git Development Community nor the\n+ *   names of its contributors may be used to endorse or promote\n+ *   products derived from this software without specific prior\n+ *   written permission.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n+ * CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+package org.spearce.jgit.treewalk.rules;\n+\n+import java.util.ArrayList;\n+import java.util.Collections;\n+import java.util.List;\n+\n+import org.spearce.jgit.errors.InvalidPatternException;\n+\n+import junit.framework.TestCase;\n+\n+public class OverallIgnoreRulesTest extends TestCase {\n+\tprivate IgnoreRulesFactory factory;\n+\n+\t@Override\n+\tprotected void setUp() throws Exception {\n+\t\tfactory = new IgnoreRulesFactory();\n+\t}\n+\n+\tpublic void testSimpleGlobalPattern() throws Exception {\n+\t\tList<String> lines = new ArrayList<String>();\n+\t\tlines.add(\"ab\");\n+\t\tfinal Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);\n+\t\tassertTrue(ignoreRules.shouldIgnore(\"ab\", false));\n+\t\tassertTrue(ignoreRules.shouldIgnore(\"ab\", true));\n+\t\tassertFalse(ignoreRules.shouldIgnore(\"abc\", false));\n+\t\tassertFalse(ignoreRules.shouldIgnore(\"abc\", true));\n+\t}\n+\n+\tpublic void testGlobalPatternWithOneStar() throws Exception {\n+\t\tList<String> lines = new ArrayList<String>();\n+\t\tlines.add(\"a*c\");\n+\t\tfinal Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);\n+\n+\t\tassertTrue(ignoreRules.shouldIgnore(\"ac\", false));\n+\t\tassertTrue(ignoreRules.shouldIgnore(\"ac\", true));\n+\n+\t\tassertTrue(ignoreRules.shouldIgnore(\"abc\", false));\n+\t\tassertTrue(ignoreRules.shouldIgnore(\"abc\", true));\n+\n+\t\tassertTrue(ignoreRules.shouldIgnore(\"abbc\", false));\n+\t\tassertTrue(ignoreRules.shouldIgnore(\"abbc\", true));\n+\n+\t\tassertTrue(ignoreRules.shouldIgnore(\"aabc\", false));\n+\t\tassertTrue(ignoreRules.shouldIgnore(\"aabc\", true));\n+\n+\t\tassertFalse(ignoreRules.shouldIgnore(\"cab\", false));\n+\t\tassertFalse(ignoreRules.shouldIgnore(\"cab\", true));\n+\t}\n+\n+\tpublic void testGlobalPatternWithTwoStars() throws Exception {\n+\t\tList<String> lines = new ArrayList<String>();\n+\t\tlines.add(\"a*c*e\");\n+\t\tfinal Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);\n+\n+\t\tassertTrue(ignoreRules.shouldIgnore(\"ace\", false));\n+\t\tassertTrue(ignoreRules.shouldIgnore(\"ace\", true));\n+\n+\t\tassertTrue(ignoreRules.shouldIgnore(\"abcde\", false));\n+\t\tassertTrue(ignoreRules.shouldIgnore(\"abcde\", true));\n+\n+\t\tassertTrue(ignoreRules.shouldIgnore(\"aHellocWorlde\", false));\n+\t\tassertTrue(ignoreRules.shouldIgnore(\"aHellocWorlde\", true));\n+\n+\t\tassertFalse(ignoreRules.shouldIgnore(\"ae\", false));\n+\t\tassertFalse(ignoreRules.shouldIgnore(\"ae\", true));\n+\t}\n+\n+\tpublic void testGlobalPatternWithDots() throws Exception {\n+\t\tList<String> lines = new ArrayList<String>();\n+\t\tlines.add(\"*.tar.gz\");\n+\t\tfinal Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);\n+\n+\t\tassertTrue(ignoreRules.shouldIgnore(\"test.tar.gz\", false));\n+\t\tassertTrue(ignoreRules.shouldIgnore(\"test.tar.gz\", true));\n+\n+\t\tassertTrue(ignoreRules.shouldIgnore(\".tar.gz\", false));\n+\t\tassertTrue(ignoreRules.shouldIgnore(\".tar.gz\", true));\n+\n+\t\tassertFalse(ignoreRules.shouldIgnore(\"test\", false));\n+\t\tassertFalse(ignoreRules.shouldIgnore(\"test\", true));\n+\n+\t\t// test that \".\" isn't handled as \"any character\"\n+\t\tassertFalse(ignoreRules.shouldIgnore(\".tarogz\", false));\n+\t\tassertFalse(ignoreRules.shouldIgnore(\".tarogz\", true));\n+\t}\n+\n+\tpublic void testGlobalPatternDirectoryOnlyRule() throws Exception {\n+\t\tList<String> lines = new ArrayList<String>();\n+\t\tlines.add(\"a/\");\n+\t\tfinal Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);\n+\n+\t\tassertTrue(ignoreRules.shouldIgnore(\"a\", true));\n+\t\tassertFalse(ignoreRules.shouldIgnore(\"a\", false));\n+\n+\t\tfinal Rules ignoreRulesA = ignoreRules.getRulesForSubDirectory(\"a\");\n+\t\tassertSame(Rules.IGNORE_ALL, ignoreRulesA);\n+\n+\t\tfinal Rules ignoreRulesB = ignoreRules.getRulesForSubDirectory(\"b\");\n+\t\tassertTrue(ignoreRulesB.shouldIgnore(\"a\", true));\n+\t\tassertFalse(ignoreRulesB.shouldIgnore(\"a\", false));\n+\n+\t\tfinal Rules ignoreRulesBA = ignoreRulesB.getRulesForSubDirectory(\"a\");\n+\t\tassertSame(Rules.IGNORE_ALL, ignoreRulesBA);\n+\n+\t}\n+\n+\tpublic void testSimpleFilePathPattern() throws Exception {\n+\t\tList<String> lines = new ArrayList<String>();\n+\t\tlines.add(\"a/b/c\");\n+\t\tfinal Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);\n+\t\tassertFalse(ignoreRules.shouldIgnore(\"a\", true));\n+\t\tassertFalse(ignoreRules.shouldIgnore(\"a\", false));\n+\t\tassertFalse(ignoreRules.shouldIgnore(\"b\", true));\n+\t\tassertFalse(ignoreRules.shouldIgnore(\"b\", false));\n+\t\tassertFalse(ignoreRules.shouldIgnore(\"c\", true));\n+\t\tassertFalse(ignoreRules.shouldIgnore(\"c\", false));\n+\n+\t\tfinal Rules ignoreRulesA = ignoreRules.getRulesForSubDirectory(\"a\");\n+\t\tassertFalse(ignoreRulesA.shouldIgnore(\"a\", true));\n+\t\tassertFalse(ignoreRulesA.shouldIgnore(\"a\", false));\n+\t\tassertFalse(ignoreRulesA.shouldIgnore(\"b\", true));\n+\t\tassertFalse(ignoreRulesA.shouldIgnore(\"b\", false));\n+\t\tassertFalse(ignoreRulesA.shouldIgnore(\"c\", true));\n+\t\tassertFalse(ignoreRulesA.shouldIgnore(\"c\", false));\n+\n+\t\tfinal Rules ignoreRulesAB = ignoreRulesA.getRulesForSubDirectory(\"b\");\n+\t\tassertFalse(ignoreRulesAB.shouldIgnore(\"a\", true));\n+\t\tassertFalse(ignoreRulesAB.shouldIgnore(\"a\", false));\n+\t\tassertFalse(ignoreRulesAB.shouldIgnore(\"b\", true));\n+\t\tassertFalse(ignoreRulesAB.shouldIgnore(\"b\", false));\n+\t\tassertTrue(ignoreRulesAB.shouldIgnore(\"c\", true));\n+\t\tassertTrue(ignoreRulesAB.shouldIgnore(\"c\", false));\n+\n+\t\tfinal Rules ignoreRulesABA = ignoreRulesAB.getRulesForSubDirectory(\"a\");\n+\t\tassertSame(Rules.IGNORE_NOTHING, ignoreRulesABA);\n+\n+\t\tfinal Rules ignoreRulesABB = ignoreRulesAB.getRulesForSubDirectory(\"b\");\n+\t\tassertSame(Rules.IGNORE_NOTHING, ignoreRulesABB);\n+\n+\t\tfinal Rules ignoreRulesABC = ignoreRulesAB.getRulesForSubDirectory(\"c\");\n+\t\tassertSame(Rules.IGNORE_ALL, ignoreRulesABC);\n+\t}\n+\n+\tpublic void testFilePathPatternDirectoryOnlyRule() throws Exception {\n+\t\tList<String> lines = new ArrayList<String>();\n+\t\tlines.add(\"a/b/c/\");\n+\t\tfinal Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);\n+\t\tassertFalse(ignoreRules.shouldIgnore(\"a\", true));\n+\t\tassertFalse(ignoreRules.shouldIgnore(\"a\", false));\n+\t\tassertFalse(ignoreRules.shouldIgnore(\"b\", true));\n+\t\tassertFalse(ignoreRules.shouldIgnore(\"b\", false));\n+\t\tassertFalse(ignoreRules.shouldIgnore(\"c\", true));\n+\t\tassertFalse(ignoreRules.shouldIgnore(\"c\", false));\n+\n+\t\tfinal Rules ignoreRulesA = ignoreRules.getRulesForSubDirectory(\"a\");\n+\t\tassertFalse(ignoreRulesA.shouldIgnore(\"a\", true));\n+\t\tassertFalse(ignoreRulesA.shouldIgnore(\"a\", false));\n+\t\tassertFalse(ignoreRulesA.shouldIgnore(\"b\", true));\n+\t\tassertFalse(ignoreRulesA.shouldIgnore(\"b\", false));\n+\t\tassertFalse(ignoreRulesA.shouldIgnore(\"c\", true));\n+\t\tassertFalse(ignoreRulesA.shouldIgnore(\"c\", false));\n+\n+\t\tfinal Rules ignoreRulesAB = ignoreRulesA.getRulesForSubDirectory(\"b\");\n+\t\tassertFalse(ignoreRulesAB.shouldIgnore(\"a\", true));\n+\t\tassertFalse(ignoreRulesAB.shouldIgnore(\"a\", false));\n+\t\tassertFalse(ignoreRulesAB.shouldIgnore(\"b\", true));\n+\t\tassertFalse(ignoreRulesAB.shouldIgnore(\"b\", false));\n+\t\tassertTrue(ignoreRulesAB.shouldIgnore(\"c\", true));\n+\t\tassertFalse(ignoreRulesAB.shouldIgnore(\"c\", false));\n+\n+\t\tfinal Rules ignoreRulesABA = ignoreRulesAB.getRulesForSubDirectory(\"a\");\n+\t\tassertSame(Rules.IGNORE_NOTHING, ignoreRulesABA);\n+\n+\t\tfinal Rules ignoreRulesABB = ignoreRulesAB.getRulesForSubDirectory(\"b\");\n+\t\tassertSame(Rules.IGNORE_NOTHING, ignoreRulesABB);\n+\n+\t\tfinal Rules ignoreRulesABC = ignoreRulesAB.getRulesForSubDirectory(\"c\");\n+\t\tassertSame(Rules.IGNORE_ALL, ignoreRulesABC);\n+\t}\n+\n+\tpublic void testShortPathPattern() throws Exception {\n+\t\tList<String> lines = new ArrayList<String>();\n+\t\tlines.add(\"/alpha\");\n+\t\tfinal Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);\n+\t\tassertTrue(ignoreRules.shouldIgnore(\"alpha\", true));\n+\t\tassertTrue(ignoreRules.shouldIgnore(\"alpha\", false));\n+\n+\t\tfinal Rules ignoreRulesAlpha = ignoreRules\n+\t\t\t\t.getRulesForSubDirectory(\"alpha\");\n+\t\tassertSame(Rules.IGNORE_ALL, ignoreRulesAlpha);\n+\n+\t\tfinal Rules ignoreRulesBeta = ignoreRules\n+\t\t\t\t.getRulesForSubDirectory(\"beta\");\n+\t\tassertSame(Rules.IGNORE_NOTHING, ignoreRulesBeta);\n+\t}\n+\n+\tpublic void testShortDirectoryPathPattern() throws Exception {\n+\t\tList<String> lines = new ArrayList<String>();\n+\t\tlines.add(\"/alpha/\");\n+\t\tfinal Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);\n+\t\tassertTrue(ignoreRules.shouldIgnore(\"alpha\", true));\n+\t\tassertFalse(ignoreRules.shouldIgnore(\"alpha\", false));\n+\n+\t\tfinal Rules ignoreRulesAlpha = ignoreRules\n+\t\t\t\t.getRulesForSubDirectory(\"alpha\");\n+\t\tassertSame(Rules.IGNORE_ALL, ignoreRulesAlpha);\n+\n+\t\tfinal Rules ignoreRulesBeta = ignoreRules\n+\t\t\t\t.getRulesForSubDirectory(\"beta\");\n+\t\tassertSame(Rules.IGNORE_NOTHING, ignoreRulesBeta);\n+\t}\n+\n+\tpublic void testShortPathPatternWithStar() throws Exception {\n+\t\tList<String> lines = new ArrayList<String>();\n+\t\tlines.add(\"/.*\");\n+\t\tfinal Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);\n+\n+\t\tassertTrue(ignoreRules.shouldIgnore(\".test\", true));\n+\t\tassertTrue(ignoreRules.shouldIgnore(\".test\", false));\n+\n+\t\tassertFalse(ignoreRules.shouldIgnore(\"test\", true));\n+\t\tassertFalse(ignoreRules.shouldIgnore(\"test\", false));\n+\n+\t\tfinal Rules ignoreRulesDotTest = ignoreRules\n+\t\t\t\t.getRulesForSubDirectory(\".test\");\n+\t\tassertSame(Rules.IGNORE_ALL, ignoreRulesDotTest);\n+\n+\t\tfinal Rules ignoreRulesTest = ignoreRules\n+\t\t\t\t.getRulesForSubDirectory(\"test\");\n+\t\tassertSame(Rules.IGNORE_NOTHING, ignoreRulesTest);\n+\t}\n+\n+\tpublic void testPathPatternWith2Times2Stars() throws Exception {\n+\t\tfinal List<String> lines = new ArrayList<String>();\n+\t\tlines.add(\"he*wor*d/*.*\");\n+\t\tfinal Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);\n+\n+\t\tassertFalse(ignoreRules.shouldIgnore(\"hello\", true));\n+\t\tassertFalse(ignoreRules.shouldIgnore(\"hello\", false));\n+\t\tfinal Rules ignoreRulesHello = ignoreRules\n+\t\t\t\t.getRulesForSubDirectory(\"hello\");\n+\t\tassertSame(Rules.IGNORE_NOTHING, ignoreRulesHello);\n+\n+\t\tassertFalse(ignoreRules.shouldIgnore(\"helloworld\", true));\n+\t\tassertFalse(ignoreRules.shouldIgnore(\"helloworld\", false));\n+\t\tfinal Rules ignoreRulesHelloWorld = ignoreRules\n+\t\t\t\t.getRulesForSubDirectory(\"helloworld\");\n+\t\tassertNotSame(Rules.IGNORE_NOTHING, ignoreRulesHelloWorld);\n+\n+\t\tassertTrue(ignoreRulesHelloWorld.shouldIgnore(\"test.txt\", true));\n+\t\tassertTrue(ignoreRulesHelloWorld.shouldIgnore(\"test.txt\", false));\n+\n+\t\tassertFalse(ignoreRulesHelloWorld.shouldIgnore(\"test\", true));\n+\t\tassertFalse(ignoreRulesHelloWorld.shouldIgnore(\"test\", false));\n+\n+\t\tfinal Rules ignoreRulesTestTxt = ignoreRulesHelloWorld\n+\t\t\t\t.getRulesForSubDirectory(\"test.txt\");\n+\t\tassertSame(Rules.IGNORE_ALL, ignoreRulesTestTxt);\n+\n+\t\tfinal Rules ignoreRulesTest = ignoreRulesHelloWorld\n+\t\t\t\t.getRulesForSubDirectory(\"test\");\n+\t\tassertSame(Rules.IGNORE_NOTHING, ignoreRulesTest);\n+\t}\n+\n+\tpublic void testEmptyIgnoreList() throws Exception {\n+\t\tfinal List<String> lines = Collections.emptyList();\n+\t\tfinal Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);\n+\t\tassertSame(Rules.IGNORE_NOTHING, ignoreRules);\n+\t}\n+\n+\tpublic void testOnlyOneNegatedIgnore() throws Exception {\n+\t\tfinal List<String> lines = new ArrayList<String>();\n+\t\tlines.add(\"!a\");\n+\t\tfinal Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);\n+\t\tassertSame(Rules.IGNORE_NOTHING, ignoreRules);\n+\t}\n+\n+\tpublic void testOnlyThreeNegatedIgnores() throws Exception {\n+\t\tfinal List<String> lines = new ArrayList<String>();\n+\t\tlines.add(\"!a\");\n+\t\tlines.add(\"!a/b/c\");\n+\t\tlines.add(\"!b*\");\n+\t\tfinal Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);\n+\t\tassertSame(Rules.IGNORE_NOTHING, ignoreRules);\n+\t}\n+\n+\tpublic void testNegatedIgnoreCase1() throws Exception {\n+\t\tfinal List<String> lines = new ArrayList<String>();\n+\t\tlines.add(\"/a\");\n+\t\tlines.add(\"!b\");\n+\t\tfinal Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);\n+\t\tfinal Rules ignoreRulesA = ignoreRules.getRulesForSubDirectory(\"a\");\n+\t\tfinal Rules ignoreRulesAB = ignoreRulesA.getRulesForSubDirectory(\"b\");\n+\t\tfinal Rules ignoreRulesB = ignoreRules.getRulesForSubDirectory(\"b\");\n+\t\tfinal Rules ignoreRulesC = ignoreRules.getRulesForSubDirectory(\"c\");\n+\t\tassertSame(Rules.IGNORE_NOTHING, ignoreRulesB);\n+\t\tassertSame(Rules.IGNORE_NOTHING, ignoreRulesAB);\n+\t\tassertSame(Rules.IGNORE_NOTHING, ignoreRulesC);\n+\t\tassertTrue(ignoreRules.shouldIgnore(\"a\", true));\n+\t\tassertTrue(ignoreRules.shouldIgnore(\"a\", false));\n+\t\tassertTrue(ignoreRulesA.shouldIgnore(\"c\", true));\n+\t\tassertTrue(ignoreRulesA.shouldIgnore(\"c\", false));\n+\t}\n+\n+\tpublic void testExceptionOfException() throws Exception {\n+\t\tfinal List<String> lines = new ArrayList<String>();\n+\t\tlines.add(\"*.*\");\n+\t\tlines.add(\"!*.c\");\n+\t\tlines.add(\"a.c\");\n+\t\tfinal Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);\n+\t\tassertTrue(ignoreRules.shouldIgnore(\"b.txt\", false));\n+\t\tassertTrue(ignoreRules.shouldIgnore(\"b.txt\", true));\n+\t\tassertTrue(ignoreRules.shouldIgnore(\"a.c\", false));\n+\t\tassertTrue(ignoreRules.shouldIgnore(\"a.c\", true));\n+\t\tassertFalse(ignoreRules.shouldIgnore(\"b.c\", false));\n+\t\tassertFalse(ignoreRules.shouldIgnore(\"b.c\", true));\n+\t}\n+\n+\tpublic void testComplexCase() throws Exception {\n+\t\tfinal List<String> lines = new ArrayList<String>();\n+\t\tlines.add(\"*\");\n+\t\tlines.add(\"!/alpha/src\");\n+\t\tlines.add(\"*~\");\n+\t\tfinal Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);\n+\t\tassertTrue(ignoreRules.shouldIgnore(\"beta\", true));\n+\t\tassertTrue(ignoreRules.shouldIgnore(\"alpha\", true));\n+\t\tfinal Rules ignoreRulesAlpha = ignoreRules\n+\t\t\t\t.getRulesForSubDirectory(\"alpha\");\n+\t\tfinal Rules ignoreRulesAlphaBin = ignoreRulesAlpha\n+\t\t\t\t.getRulesForSubDirectory(\"bin\");\n+\t\tfinal Rules ignoreRulesAlphaSrc = ignoreRulesAlpha\n+\t\t\t\t.getRulesForSubDirectory(\"src\");\n+\t\tassertSame(Rules.IGNORE_ALL, ignoreRulesAlphaBin);\n+\t\tassertFalse(ignoreRulesAlphaSrc.shouldIgnore(\"com\", true));\n+\t\tassertFalse(ignoreRulesAlphaSrc.shouldIgnore(\"b.java\", false));\n+\t\tassertTrue(ignoreRulesAlphaSrc.shouldIgnore(\"b.java~\", true));\n+\t}\n+\n+\tprivate class IgnoreRulesFactory {\n+\t\tprivate RuleListToObjectConverter converter = new RuleListToObjectConverter();\n+\n+\t\tprivate IgnoreRuleListFactory listFactory = new IgnoreRuleListFactory();\n+\n+\t\t/**\n+\t\t * @param ignoreFileLines\n+\t\t *            the lines of a ignore file like .gitignore.\n+\t\t * @return a immutable IgnoreRules object.\n+\t\t * @throws InvalidPatternException\n+\t\t */\n+\t\tpublic Rules createIgnoreRulesFromLines(Iterable<String> ignoreFileLines)\n+\t\t\t\tthrows InvalidPatternException {\n+\t\t\tfinal List<Rule> rules = listFactory\n+\t\t\t\t\t.createIgnoreRuleList(ignoreFileLines);\n+\t\t\treturn converter.createIgnoreRules(rules.iterator());\n+\t\t}\n+\n+\t}\n+\n+}\n-- \n1.5.4.3\n"},{"id":"79753","messageId":"1213382121-19786-10-git-send-email-florianskarten@web.de","threadId":"13934","inReplyTo":"4852BCCA.4030404@web.de","subject":"[JGIT PATCH v4 10/24] Added the class PathNotInProjectDirectoryException.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-06-13T18:35:07Z","receivedAt":"2008-06-13T18:35:07Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Signed-off-by: Florian Koeberle <florianskarten@web.de>\n---\n .../errors/PathNotInProjectDirectoryException.java |   46 ++++++++++++++++++++\n 1 files changed, 46 insertions(+), 0 deletions(-)\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/errors/PathNotInProjectDirectoryException.java\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/errors/PathNotInProjectDirectoryException.java b/org.spearce.jgit/src/org/spearce/jgit/errors/PathNotInProjectDirectoryException.java\nnew file mode 100644\nindex 0000000..5fce2b3\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/errors/PathNotInProjectDirectoryException.java\n@@ -0,0 +1,46 @@\n+/*\n+ * Copyright (C) 2008, Florian KÃ¶berle <florianskarten@web.de>\n+ *\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or\n+ * without modification, are permitted provided that the following\n+ * conditions are met:\n+ *\n+ * - Redistributions of source code must retain the above copyright\n+ *   notice, this list of conditions and the following disclaimer.\n+ *\n+ * - Redistributions in binary form must reproduce the above\n+ *   copyright notice, this list of conditions and the following\n+ *   disclaimer in the documentation and/or other materials provided\n+ *   with the distribution.\n+ *\n+ * - Neither the name of the Git Development Community nor the\n+ *   names of its contributors may be used to endorse or promote\n+ *   products derived from this software without specific prior\n+ *   written permission.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n+ * CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+package org.spearce.jgit.errors;\n+\n+/**\n+ * Thrown when a path wasn't in the project directory, but expected to be.\n+ * \n+ */\n+public class PathNotInProjectDirectoryException extends\n+\t\tIllegalArgumentException {\n+}\n-- \n1.5.4.3\n"},{"id":"79761","messageId":"1213382121-19786-11-git-send-email-florianskarten@web.de","threadId":"13934","inReplyTo":"4852BCCA.4030404@web.de","subject":"[JGIT PATCH v4 11/24] Added the class AddRuleListFactory.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-06-13T18:35:08Z","receivedAt":"2008-06-13T18:35:08Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Signed-off-by: Florian Koeberle <florianskarten@web.de>\n---\n .../jgit/treewalk/rules/AddRuleListFactory.java    |   96 ++++++++++++++++++++\n 1 files changed, 96 insertions(+), 0 deletions(-)\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/AddRuleListFactory.java\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/AddRuleListFactory.java b/org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/AddRuleListFactory.java\nnew file mode 100644\nindex 0000000..5304a38\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/AddRuleListFactory.java\n@@ -0,0 +1,96 @@\n+/*\n+ * Copyright (C) 2008, Florian KÃ¶berle <florianskarten@web.de>\n+ *\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or\n+ * without modification, are permitted provided that the following\n+ * conditions are met:\n+ *\n+ * - Redistributions of source code must retain the above copyright\n+ *   notice, this list of conditions and the following disclaimer.\n+ *\n+ * - Redistributions in binary form must reproduce the above\n+ *   copyright notice, this list of conditions and the following\n+ *   disclaimer in the documentation and/or other materials provided\n+ *   with the distribution.\n+ *\n+ * - Neither the name of the Git Development Community nor the\n+ *   names of its contributors may be used to endorse or promote\n+ *   products derived from this software without specific prior\n+ *   written permission.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n+ * CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+package org.spearce.jgit.treewalk.rules;\n+\n+import java.io.File;\n+import java.io.IOException;\n+import java.util.ArrayList;\n+import java.util.List;\n+\n+import org.spearce.jgit.errors.InvalidPatternException;\n+import org.spearce.jgit.errors.PathNotInProjectDirectoryException;\n+\n+class AddRuleListFactory {\n+\n+\tprivate static String getRelativeUnixPath(File projectDirectory, File file)\n+\t\t\tthrows PathNotInProjectDirectoryException, IOException {\n+\t\tfinal StringBuilder resultBuilder = new StringBuilder();\n+\t\tFile currentFile = file.getCanonicalFile();\n+\t\twhile (!currentFile.equals(projectDirectory)) {\n+\t\t\tif (resultBuilder.length() > 0) {\n+\t\t\t\tresultBuilder.insert(0, '/');\n+\t\t\t}\n+\t\t\tresultBuilder.insert(0, currentFile.getName());\n+\t\t\tcurrentFile = currentFile.getParentFile();\n+\t\t\tif (currentFile == null) {\n+\t\t\t\tthrow new PathNotInProjectDirectoryException();\n+\t\t\t}\n+\t\t}\n+\t\treturn resultBuilder.toString();\n+\t}\n+\n+\tList<Rule> createRuleList(File projectDirectory, File workingDirectory,\n+\t\t\tList<String> filePatternsOfAddCommand)\n+\t\t\tthrows PathNotInProjectDirectoryException, IOException,\n+\t\t\tInvalidPatternException {\n+\n+\t\tfinal String workingDirectoryPath = getRelativeUnixPath(\n+\t\t\t\tprojectDirectory, workingDirectory);\n+\n+\t\tfinal List<Rule> ruleList = new ArrayList<Rule>(\n+\t\t\t\tfilePatternsOfAddCommand.size());\n+\t\tfor (String pattern : filePatternsOfAddCommand) {\n+\t\t\tboolean matchDirectoriesOnly = false;\n+\t\t\tif (pattern.endsWith(File.separator)) {\n+\t\t\t\tpattern = pattern.substring(0, pattern.length() - 1);\n+\t\t\t\tmatchDirectoriesOnly = true;\n+\t\t\t}\n+\t\t\tpattern = pattern.replace(File.separatorChar, '/');\n+\t\t\tif (!\"\".equals(workingDirectoryPath)) {\n+\t\t\t\tpattern = workingDirectoryPath + \"/\" + pattern;\n+\n+\t\t\t}\n+\t\t\tfinal FilePattern filePattern = new FilePathPattern(pattern, true,\n+\t\t\t\t\tmatchDirectoriesOnly);\n+\t\t\tfinal Rule rule = new Rule(false, filePattern);\n+\t\t\truleList.add(rule);\n+\n+\t\t}\n+\t\treturn ruleList;\n+\t}\n+}\n-- \n1.5.4.3\n"},{"id":"79772","messageId":"1213382121-19786-12-git-send-email-florianskarten@web.de","threadId":"13934","inReplyTo":"4852BCCA.4030404@web.de","subject":"[JGIT PATCH v4 12/24] Formatted Constants class.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-06-13T18:35:09Z","receivedAt":"2008-06-13T18:35:09Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Signed-off-by: Florian Koeberle <florianskarten@web.de>\nSigned-off-by: Shawn O. Pearce <spearce@spearce.org>\n---\n .../src/org/spearce/jgit/lib/Constants.java        |   14 ++++++++------\n 1 files changed, 8 insertions(+), 6 deletions(-)\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Constants.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Constants.java\nindex d1e8a41..26b8c8e 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/Constants.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Constants.java\n@@ -226,8 +226,9 @@ public final class Constants {\n \n \t/**\n \t * Convert an OBJ_* type constant to a TYPE_* type constant.\n-\t *\n-\t * @param typeCode the type code, from a pack representation.\n+\t * \n+\t * @param typeCode\n+\t *            the type code, from a pack representation.\n \t * @return the canonical string name of this type.\n \t */\n \tpublic static String typeString(final int typeCode) {\n@@ -248,10 +249,11 @@ public final class Constants {\n \t/**\n \t * Convert an OBJ_* type constant to an ASCII encoded string constant.\n \t * <p>\n-\t * The ASCII encoded string is often the canonical representation of\n-\t * the type within a loose object header, or within a tag header.\n-\t *\n-\t * @param typeCode the type code, from a pack representation.\n+\t * The ASCII encoded string is often the canonical representation of the\n+\t * type within a loose object header, or within a tag header.\n+\t * \n+\t * @param typeCode\n+\t *            the type code, from a pack representation.\n \t * @return the canonical ASCII encoded name of this type.\n \t */\n \tpublic static byte[] encodedTypeString(final int typeCode) {\n-- \n1.5.4.3\n"},{"id":"79769","messageId":"1213382121-19786-13-git-send-email-florianskarten@web.de","threadId":"13934","inReplyTo":"4852BCCA.4030404@web.de","subject":"[JGIT PATCH v4 13/24] Added constant REPOSITORY_DIRECTORY_NAME to Constants class.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-06-13T18:35:10Z","receivedAt":"2008-06-13T18:35:10Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Signed-off-by: Florian Koeberle <florianskarten@web.de>\nSigned-off-by: Shawn O. Pearce <spearce@spearce.org>\n---\n .../src/org/spearce/jgit/lib/Constants.java        |    6 ++++++\n 1 files changed, 6 insertions(+), 0 deletions(-)\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Constants.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Constants.java\nindex 26b8c8e..744d4d8 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/Constants.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Constants.java\n@@ -207,6 +207,12 @@ public final class Constants {\n \tpublic static final String TAGS_PREFIX = \"refs/tags\";\n \n \t/**\n+\t * The name of the repository directory in the project directory. Project\n+\t * directory means here the tree under version control.\n+\t */\n+\tpublic static final String REPOSITORY_DIRECTORY_NAME = \".git\";\n+\n+\t/**\n \t * Create a new digest function for objects.\n \t * \n \t * @return a new digest object.\n-- \n1.5.4.3\n"},{"id":"79766","messageId":"1213382121-19786-14-git-send-email-florianskarten@web.de","threadId":"13934","inReplyTo":"4852BCCA.4030404@web.de","subject":"[JGIT PATCH v4 14/24] Added class AddRulesFactory.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-06-13T18:35:11Z","receivedAt":"2008-06-13T18:35:11Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Signed-off-by: Florian Koeberle <florianskarten@web.de>\n---\n .../jgit/treewalk/rules/AddRulesFactory.java       |  127 ++++++++++++++++++++\n 1 files changed, 127 insertions(+), 0 deletions(-)\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/AddRulesFactory.java\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/AddRulesFactory.java b/org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/AddRulesFactory.java\nnew file mode 100644\nindex 0000000..767b5c7\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/AddRulesFactory.java\n@@ -0,0 +1,127 @@\n+/*\n+ * Copyright (C) 2008, Florian KÃ¶berle <florianskarten@web.de>\n+ *\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or\n+ * without modification, are permitted provided that the following\n+ * conditions are met:\n+ *\n+ * - Redistributions of source code must retain the above copyright\n+ *   notice, this list of conditions and the following disclaimer.\n+ *\n+ * - Redistributions in binary form must reproduce the above\n+ *   copyright notice, this list of conditions and the following\n+ *   disclaimer in the documentation and/or other materials provided\n+ *   with the distribution.\n+ *\n+ * - Neither the name of the Git Development Community nor the\n+ *   names of its contributors may be used to endorse or promote\n+ *   products derived from this software without specific prior\n+ *   written permission.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n+ * CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+package org.spearce.jgit.treewalk.rules;\n+\n+import java.io.File;\n+import java.io.FileNotFoundException;\n+import java.io.IOException;\n+import java.util.ArrayList;\n+import java.util.List;\n+\n+import org.spearce.jgit.errors.InvalidPatternException;\n+import org.spearce.jgit.errors.PathNotInProjectDirectoryException;\n+import static org.spearce.jgit.lib.Constants.REPOSITORY_DIRECTORY_NAME;\n+\n+/**\n+ * This class is designed to serve the needs of someone who want to implement a\n+ * git-add command and needs to determine the files to add.\n+ * \n+ */\n+public class AddRulesFactory {\n+\tprivate final RuleListToObjectConverter converter = new RuleListToObjectConverter();\n+\n+\tprivate final IgnoreRuleListFactory ignoreRuleListFactory = new IgnoreRuleListFactory();\n+\n+\tprivate final AddRuleListFactory addRuleListFactory = new AddRuleListFactory();\n+\n+\t/**\n+\t * @param workTreeDirectory\n+\t *            The directory with the files of the project under version\n+\t *            control.\n+\t * @param workingDirectory\n+\t *            a directory within the workTreeDirectory.\n+\t * @param filePatternsOfAddCommand\n+\t *            the file patterns passed to the add command.\n+\t * @return a {@link Rules} containing the specified rules, the .gitignore\n+\t *         and the .git/info/exclude rules.\n+\t * @throws InvalidPatternException\n+\t *             if a pattern is invalid.\n+\t * @throws PathNotInProjectDirectoryException\n+\t *             if the directory workingDirectory is not in workTreeDirectory\n+\t * @throws IOException\n+\t *             for some reasons.\n+\t */\n+\tpublic Rules createRules(File workTreeDirectory, File workingDirectory,\n+\t\t\tList<String> filePatternsOfAddCommand)\n+\t\t\tthrows InvalidPatternException, PathNotInProjectDirectoryException,\n+\t\t\tIOException {\n+\t\tfinal Rule gitDirectoryIgnoreRule = createGitDirectoryIgnoreRule();\n+\t\tfinal File gitDirectory = new File(workTreeDirectory,\n+\t\t\t\tREPOSITORY_DIRECTORY_NAME);\n+\t\tfinal List<Rule> ignoreRuleListFromFiles = createExcludeRules(\n+\t\t\t\tworkTreeDirectory, gitDirectory);\n+\t\tfinal List<Rule> includeRules = addRuleListFactory.createRuleList(\n+\t\t\t\tworkTreeDirectory, workingDirectory, filePatternsOfAddCommand);\n+\t\tfinal List<Rule> ruleList = new ArrayList<Rule>();\n+\n+\t\truleList.add(gitDirectoryIgnoreRule);\n+\t\truleList.addAll(ignoreRuleListFromFiles);\n+\t\truleList.addAll(includeRules);\n+\t\truleList.add(new Rule(true, FilePattern.MATCH_ALWAYS));\n+\n+\t\treturn converter.createIgnoreRules(ruleList.iterator());\n+\t}\n+\n+\tprivate List<Rule> createExcludeRules(File projectDirectory,\n+\t\t\tFile gitDirectory) throws InvalidPatternException {\n+\t\tfinal List<File> possibleIgnoreFiles = new ArrayList<File>(2);\n+\t\tpossibleIgnoreFiles.add(new File(projectDirectory, \".gitignore\"));\n+\t\tpossibleIgnoreFiles.add(new File(new File(gitDirectory, \"info\"),\n+\t\t\t\t\"exclude\"));\n+\n+\t\tfinal List<File> ignoreFiles = new ArrayList<File>();\n+\t\tfor (File possibleIgnoreFile : possibleIgnoreFiles) {\n+\t\t\tif (possibleIgnoreFile.isFile()) {\n+\t\t\t\tignoreFiles.add(possibleIgnoreFile);\n+\t\t\t}\n+\t\t}\n+\n+\t\ttry {\n+\t\t\treturn ignoreRuleListFactory.createIgnoreRuleList(ignoreFiles);\n+\t\t} catch (FileNotFoundException e) {\n+\t\t\tthrow new RuntimeException(\"unexpected removal of ignore files\", e);\n+\t\t}\n+\t}\n+\n+\tprivate Rule createGitDirectoryIgnoreRule() throws InvalidPatternException {\n+\t\tfinal FilePattern gitDirectoryPattern = new FilePathPattern(\n+\t\t\t\tREPOSITORY_DIRECTORY_NAME, true, true);\n+\t\tfinal Rule gitDirectoryIgnoreRule = new Rule(true, gitDirectoryPattern);\n+\t\treturn gitDirectoryIgnoreRule;\n+\t}\n+}\n-- \n1.5.4.3\n"},{"id":"79767","messageId":"1213382121-19786-15-git-send-email-florianskarten@web.de","threadId":"13934","inReplyTo":"4852BCCA.4030404@web.de","subject":"[JGIT PATCH v4 15/24] Added the class LightFileTreeIterator and a test for it.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-06-13T18:35:12Z","receivedAt":"2008-06-13T18:35:12Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Signed-off-by: Florian Koeberle <florianskarten@web.de>\n---\n .../jgit/treewalk/LightFileTreeIteratorTest.java   |  135 ++++++++++++++++++++\n .../jgit/treewalk/LightFileTreeIterator.java       |  133 +++++++++++++++++++\n 2 files changed, 268 insertions(+), 0 deletions(-)\n create mode 100644 org.spearce.jgit.test/tst/org/spearce/jgit/treewalk/LightFileTreeIteratorTest.java\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/treewalk/LightFileTreeIterator.java\n\ndiff --git a/org.spearce.jgit.test/tst/org/spearce/jgit/treewalk/LightFileTreeIteratorTest.java b/org.spearce.jgit.test/tst/org/spearce/jgit/treewalk/LightFileTreeIteratorTest.java\nnew file mode 100644\nindex 0000000..d1d8f48\n--- /dev/null\n+++ b/org.spearce.jgit.test/tst/org/spearce/jgit/treewalk/LightFileTreeIteratorTest.java\n@@ -0,0 +1,135 @@\n+/*\n+ * Copyright (C) 2008, Florian KÃ¶berle <florianskarten@web.de>\n+ *\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or\n+ * without modification, are permitted provided that the following\n+ * conditions are met:\n+ *\n+ * - Redistributions of source code must retain the above copyright\n+ *   notice, this list of conditions and the following disclaimer.\n+ *\n+ * - Redistributions in binary form must reproduce the above\n+ *   copyright notice, this list of conditions and the following\n+ *   disclaimer in the documentation and/or other materials provided\n+ *   with the distribution.\n+ *\n+ * - Neither the name of the Git Development Community nor the\n+ *   names of its contributors may be used to endorse or promote\n+ *   products derived from this software without specific prior\n+ *   written permission.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n+ * CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+package org.spearce.jgit.treewalk;\n+\n+import java.io.File;\n+import java.util.HashSet;\n+import java.util.Iterator;\n+import java.util.Set;\n+\n+import org.spearce.jgit.treewalk.rules.Rules;\n+\n+import junit.framework.TestCase;\n+\n+public class LightFileTreeIteratorTest extends TestCase {\n+\tprivate String DIRECTORY_A_NAME = \"a\";\n+\n+\tprivate String DIRECTORY_AB_NAME = \"b\";\n+\n+\tprivate File projectDirectory;\n+\n+\tprivate File fileB;\n+\n+\tprivate File directoryA;\n+\n+\tprivate File directoryAB;\n+\n+\tprivate File fileABA;\n+\n+\tprivate File directoryAC;\n+\n+\tprivate File fileACA;\n+\n+\tprivate File fileACB;\n+\n+\t@Override\n+\tprotected void setUp() throws Exception {\n+\t\tthis.projectDirectory = File.createTempFile(\"FileTreeIteratorTest\", \"\");\n+\t\tprojectDirectory.delete();\n+\t\tprojectDirectory.mkdir();\n+\t\tprojectDirectory.deleteOnExit();\n+\n+\t\tthis.directoryA = new File(projectDirectory, DIRECTORY_A_NAME);\n+\t\tdirectoryA.mkdir();\n+\n+\t\tthis.directoryAB = new File(directoryA, DIRECTORY_AB_NAME);\n+\t\tdirectoryAB.mkdir();\n+\n+\t\tthis.fileABA = new File(directoryAB, \"a.y\");\n+\t\tfileABA.createNewFile();\n+\n+\t\tthis.directoryAC = new File(directoryA, \"c\");\n+\t\tthis.directoryAC.mkdir();\n+\n+\t\tthis.fileACA = new File(directoryAC, \"a.x\");\n+\t\tfileACA.createNewFile();\n+\n+\t\tthis.fileACB = new File(directoryAC, \"b.y\");\n+\t\tfileACB.createNewFile();\n+\n+\t\tthis.fileB = new File(projectDirectory, \"b.x\");\n+\t\tfileB.createNewFile();\n+\t}\n+\n+\tpublic void testFileTreeIterator() {\n+\t\tfinal Iterator<File> iterator = new LightFileTreeIterator(\n+\t\t\t\tprojectDirectory, Rules.IGNORE_NOTHING, false);\n+\t\tfinal Set<File> actualPaths = new HashSet<File>();\n+\t\twhile (iterator.hasNext()) {\n+\t\t\tfinal File next = iterator.next();\n+\t\t\tassertFalse(actualPaths.contains(next));\n+\t\t\tactualPaths.add(next);\n+\t\t}\n+\n+\t\tfinal Set<File> expectedPaths = new HashSet<File>();\n+\t\texpectedPaths.add(directoryA);\n+\t\texpectedPaths.add(fileB);\n+\t\texpectedPaths.add(directoryAB);\n+\t\texpectedPaths.add(fileABA);\n+\t\texpectedPaths.add(directoryAC);\n+\t\texpectedPaths.add(fileACA);\n+\t\texpectedPaths.add(fileACB);\n+\t\tassertEquals(expectedPaths, actualPaths);\n+\n+\t}\n+\n+\tpublic void testFileTreeIteratorWithIgnoreAllRules() {\n+\t\tfinal Iterator<File> iterator = new LightFileTreeIterator(\n+\t\t\t\tprojectDirectory, Rules.IGNORE_ALL, false);\n+\t\tfinal Set<File> actualPaths = new HashSet<File>();\n+\t\twhile (iterator.hasNext()) {\n+\t\t\tfinal File next = iterator.next();\n+\t\t\tassertFalse(actualPaths.contains(next));\n+\t\t\tactualPaths.add(next);\n+\t\t}\n+\n+\t\tassertEquals(0, actualPaths.size());\n+\n+\t}\n+\n+}\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/treewalk/LightFileTreeIterator.java b/org.spearce.jgit/src/org/spearce/jgit/treewalk/LightFileTreeIterator.java\nnew file mode 100644\nindex 0000000..ae80393\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/treewalk/LightFileTreeIterator.java\n@@ -0,0 +1,133 @@\n+/*\n+ * Copyright (C) 2008, Florian KÃ¶berle <florianskarten@web.de>\n+ *\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or\n+ * without modification, are permitted provided that the following\n+ * conditions are met:\n+ *\n+ * - Redistributions of source code must retain the above copyright\n+ *   notice, this list of conditions and the following disclaimer.\n+ *\n+ * - Redistributions in binary form must reproduce the above\n+ *   copyright notice, this list of conditions and the following\n+ *   disclaimer in the documentation and/or other materials provided\n+ *   with the distribution.\n+ *\n+ * - Neither the name of the Git Development Community nor the\n+ *   names of its contributors may be used to endorse or promote\n+ *   products derived from this software without specific prior\n+ *   written permission.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n+ * CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+package org.spearce.jgit.treewalk;\n+\n+import java.io.File;\n+import java.util.EmptyStackException;\n+import java.util.Iterator;\n+import java.util.NoSuchElementException;\n+import java.util.Stack;\n+\n+import org.spearce.jgit.treewalk.rules.Rules;\n+\n+class LightFileTreeIterator implements Iterator<File> {\n+\tprivate final Stack<File> remainingPaths;\n+\n+\tprivate final Stack<Directory> remainingDirectories;\n+\n+\t/**\n+\t * Creates a new Iterator which allows to iterate over the content of the\n+\t * specified rootDirectory. The rootDirectory itself is never included.\n+\t * \n+\t * @param rootDirectory\n+\t *            the directory tree to iterate over.\n+\t * @param ignoreRules\n+\t *            defines which paths are included and which aren't.\n+\t * @param includeRootDirectory\n+\t *            the iterator will return the rootDirectory if this is flag is\n+\t *            true.\n+\t */\n+\tLightFileTreeIterator(File rootDirectory, Rules ignoreRules,\n+\t\t\tboolean includeRootDirectory) {\n+\t\tremainingPaths = new Stack<File>();\n+\t\tif (includeRootDirectory) {\n+\t\t\tremainingPaths.add(rootDirectory);\n+\t\t}\n+\t\tremainingDirectories = new Stack<Directory>();\n+\t\tremainingDirectories.add(new Directory(rootDirectory, ignoreRules));\n+\t}\n+\n+\tpublic boolean hasNext() {\n+\t\tfindMorePathsIfNessesary();\n+\t\treturn !remainingPaths.empty();\n+\t}\n+\n+\tvoid findMorePathsIfNessesary() {\n+\t\tif (remainingPaths.isEmpty()) {\n+\t\t\tfindMorePaths();\n+\t\t}\n+\t}\n+\n+\tvoid findMorePaths() {\n+\t\twhile (!remainingDirectories.isEmpty() && remainingPaths.isEmpty()) {\n+\t\t\tfinal Directory directory = remainingDirectories.pop();\n+\t\t\tfinal File[] paths = directory.path.listFiles();\n+\t\t\tfor (File path : paths) {\n+\t\t\t\tfinal boolean fileIsDirectory = path.isDirectory();\n+\t\t\t\tif (fileIsDirectory) {\n+\t\t\t\t\tfinal Rules subDirectoryIgnoreRules = directory.ignoreRules\n+\t\t\t\t\t\t\t.getRulesForSubDirectory(path.getName());\n+\t\t\t\t\tif (subDirectoryIgnoreRules != Rules.IGNORE_ALL) {\n+\t\t\t\t\t\tfinal Directory subDirectory = new Directory(path,\n+\t\t\t\t\t\t\t\tsubDirectoryIgnoreRules);\n+\t\t\t\t\t\tremainingDirectories.add(subDirectory);\n+\t\t\t\t\t}\n+\t\t\t\t}\n+\t\t\t\tif (!directory.ignoreRules.shouldIgnore(path.getName(),\n+\t\t\t\t\t\tfileIsDirectory)) {\n+\t\t\t\t\tremainingPaths.add(path);\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\tpublic File next() {\n+\t\tfindMorePathsIfNessesary();\n+\t\ttry {\n+\t\t\treturn remainingPaths.pop();\n+\t\t} catch (EmptyStackException e) {\n+\t\t\tthrow new NoSuchElementException();\n+\t\t}\n+\t}\n+\n+\tpublic void remove() {\n+\t\tthrow new UnsupportedOperationException();\n+\t}\n+\n+\tprivate class Directory {\n+\t\tfinal File path;\n+\n+\t\tfinal Rules ignoreRules;\n+\n+\t\tDirectory(File path, Rules ignoreRules) {\n+\t\t\tthis.path = path;\n+\t\t\tthis.ignoreRules = ignoreRules;\n+\t\t}\n+\t}\n+\n+}\n-- \n1.5.4.3\n"},{"id":"79764","messageId":"1213382121-19786-16-git-send-email-florianskarten@web.de","threadId":"13934","inReplyTo":"4852BCCA.4030404@web.de","subject":"[JGIT PATCH v4 16/24] Added class LightFileTreeIterable.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-06-13T18:35:13Z","receivedAt":"2008-06-13T18:35:13Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Signed-off-by: Florian Koeberle <florianskarten@web.de>\n---\n .../jgit/treewalk/LightFileTreeIterable.java       |   80 ++++++++++++++++++++\n 1 files changed, 80 insertions(+), 0 deletions(-)\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/treewalk/LightFileTreeIterable.java\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/treewalk/LightFileTreeIterable.java b/org.spearce.jgit/src/org/spearce/jgit/treewalk/LightFileTreeIterable.java\nnew file mode 100644\nindex 0000000..ea06e2d\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/treewalk/LightFileTreeIterable.java\n@@ -0,0 +1,80 @@\n+/*\n+ * Copyright (C) 2008, Florian KÃ¶berle <florianskarten@web.de>\n+ *\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or\n+ * without modification, are permitted provided that the following\n+ * conditions are met:\n+ *\n+ * - Redistributions of source code must retain the above copyright\n+ *   notice, this list of conditions and the following disclaimer.\n+ *\n+ * - Redistributions in binary form must reproduce the above\n+ *   copyright notice, this list of conditions and the following\n+ *   disclaimer in the documentation and/or other materials provided\n+ *   with the distribution.\n+ *\n+ * - Neither the name of the Git Development Community nor the\n+ *   names of its contributors may be used to endorse or promote\n+ *   products derived from this software without specific prior\n+ *   written permission.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n+ * CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+package org.spearce.jgit.treewalk;\n+\n+import java.io.File;\n+import java.util.Iterator;\n+\n+import org.spearce.jgit.treewalk.rules.Rules;\n+\n+/**\n+ * Use this class to iterate over some by rules determined files in a project\n+ * directory.\n+ * \n+ */\n+public class LightFileTreeIterable implements Iterable<File> {\n+\tprivate final File projectDirectory;\n+\n+\tprivate final Rules ignoreRules;\n+\n+\tprivate final boolean includeRootDirectory;\n+\n+\t/**\n+\t * \n+\t * @param workTreeDirectory\n+\t *            directory with the files which are under version control.\n+\t * @param rules\n+\t *            a {@link Rules} instance which is used to determine which file\n+\t *            are included and which not.\n+\t * @param includeWorkTreeDirectory\n+\t *            determines if the iterators should return the\n+\t *            workTreeDirectory\n+\t */\n+\tpublic LightFileTreeIterable(File workTreeDirectory, Rules rules,\n+\t\t\tboolean includeWorkTreeDirectory) {\n+\t\tthis.projectDirectory = workTreeDirectory;\n+\t\tthis.ignoreRules = rules;\n+\t\tthis.includeRootDirectory = includeWorkTreeDirectory;\n+\t}\n+\n+\tpublic Iterator<File> iterator() {\n+\t\treturn new LightFileTreeIterator(projectDirectory, ignoreRules,\n+\t\t\t\tincludeRootDirectory);\n+\t}\n+\n+}\n-- \n1.5.4.3\n"},{"id":"79755","messageId":"1213382121-19786-17-git-send-email-florianskarten@web.de","threadId":"13934","inReplyTo":"4852BCCA.4030404@web.de","subject":"[JGIT PATCH v4 17/24] Added path related constants to the Constants class.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-06-13T18:35:14Z","receivedAt":"2008-06-13T18:35:14Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Signed-off-by: Shawn O. Pearce <spearce@spearce.org>\nSigned-off-by: Florian Koeberle <florianskarten@web.de>\n---\n .../src/org/spearce/jgit/lib/Constants.java        |   10 ++++++++++\n 1 files changed, 10 insertions(+), 0 deletions(-)\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Constants.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Constants.java\nindex 744d4d8..ee85ded 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/Constants.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Constants.java\n@@ -213,6 +213,16 @@ public final class Constants {\n \tpublic static final String REPOSITORY_DIRECTORY_NAME = \".git\";\n \n \t/**\n+\t * Contains the name of the objects directory in the repository directory.\n+\t */\n+\tpublic static final String OBJECTS_DIRECTORY_NAME = \"objects\";\n+\n+\t/**\n+\t * Contains the name of the refs directory in the repository directory.\n+\t */\n+\tpublic static final String REFS_DIRECTORY_NAME = \"refs\";\n+\n+\t/**\n \t * Create a new digest function for objects.\n \t * \n \t * @return a new digest object.\n-- \n1.5.4.3\n"},{"id":"79762","messageId":"1213382121-19786-18-git-send-email-florianskarten@web.de","threadId":"13934","inReplyTo":"4852BCCA.4030404@web.de","subject":"[JGIT PATCH v4 18/24] Added WorkTree class which can be constructed over Repository.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-06-13T18:35:15Z","receivedAt":"2008-06-13T18:35:15Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Signed-off-by: Florian Koeberle <florianskarten@web.de>\n---\n .../src/org/spearce/jgit/lib/Repository.java       |   31 ++++++++\n .../src/org/spearce/jgit/lib/WorkTree.java         |   81 ++++++++++++++++++++\n 2 files changed, 112 insertions(+), 0 deletions(-)\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/WorkTree.java\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java\nindex 3efe60b..5a21c6e 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java\n@@ -986,4 +986,35 @@ public class Repository {\n \tpublic File getWorkDir() {\n \t\treturn getDirectory().getParentFile();\n \t}\n+\n+\t/**\n+\t * Creates a new {@link WorkTree} and initialize a repository for it.\n+\t * \n+\t * @param workTreeDirectory\n+\t *            the directory with the project files.\n+\t * @return a new {@link WorkTree} with a new and open {@link Repository}.\n+\t * @throws IOException\n+\t *             thrown by {@link Repository#create()}\n+\t */\n+\tpublic static WorkTree createWorkTree(File workTreeDirectory)\n+\t\t\tthrows IOException {\n+\t\tfinal File gitDirectory = new File(workTreeDirectory,\n+\t\t\t\tConstants.REPOSITORY_DIRECTORY_NAME);\n+\t\tif (gitDirectory.exists()) {\n+\t\t\tthrow new IllegalArgumentException(\n+\t\t\t\t\t\"Repository exists in given project directory.\");\n+\t\t}\n+\t\tfinal Repository repository = new Repository(gitDirectory);\n+\t\ttry {\n+\t\t\trepository.create();\n+\t\t\treturn new WorkTree(workTreeDirectory, repository);\n+\t\t} catch (RuntimeException e) {\n+\t\t\trepository.close();\n+\t\t\tthrow e;\n+\t\t} catch (IOException e) {\n+\t\t\trepository.close();\n+\t\t\tthrow e;\n+\t\t}\n+\t}\n+\n }\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/WorkTree.java b/org.spearce.jgit/src/org/spearce/jgit/lib/WorkTree.java\nnew file mode 100644\nindex 0000000..0040954\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/WorkTree.java\n@@ -0,0 +1,81 @@\n+/*\n+ * Copyright (C) 2008, Florian KÃ¶berle <florianskarten@web.de>\n+ *\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or\n+ * without modification, are permitted provided that the following\n+ * conditions are met:\n+ *\n+ * - Redistributions of source code must retain the above copyright\n+ *   notice, this list of conditions and the following disclaimer.\n+ *\n+ * - Redistributions in binary form must reproduce the above\n+ *   copyright notice, this list of conditions and the following\n+ *   disclaimer in the documentation and/or other materials provided\n+ *   with the distribution.\n+ *\n+ * - Neither the name of the Git Development Community nor the\n+ *   names of its contributors may be used to endorse or promote\n+ *   products derived from this software without specific prior\n+ *   written permission.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n+ * CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+package org.spearce.jgit.lib;\n+\n+import java.io.File;\n+\n+/**\n+ * Represents a work tree controlled by git. Use {@link Repository} in order to\n+ * create an object of this class.\n+ * \n+ */\n+public class WorkTree {\n+\tprivate final File directory;\n+\n+\tprivate final Repository repository;\n+\n+\t/**\n+\t * This constructor should be only used by the class {@link Repository}.\n+\t * \n+\t * @param directory\n+\t *            defines the value of the directory field.\n+\t * @param repository\n+\t *            defines the value of the repository field.\n+\t */\n+\tWorkTree(File directory, Repository repository) {\n+\t\tthis.directory = directory;\n+\t\tthis.repository = repository;\n+\t}\n+\n+\t/**\n+\t * \n+\t * @return the directory which contains the files of the project. Usually\n+\t *         this directory contain a .git directory with the repository.\n+\t */\n+\tpublic File getDirectory() {\n+\t\treturn directory;\n+\t}\n+\n+\t/**\n+\t * @return the {@link Repository} object of the project.\n+\t */\n+\tpublic Repository getRepository() {\n+\t\treturn repository;\n+\t}\n+\n+}\n-- \n1.5.4.3\n"},{"id":"79763","messageId":"1213382121-19786-19-git-send-email-florianskarten@web.de","threadId":"13934","inReplyTo":"4852BCCA.4030404@web.de","subject":"[JGIT PATCH v4 19/24] Added the class NoGitRepositoryFoundException.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-06-13T18:35:16Z","receivedAt":"2008-06-13T18:35:16Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Signed-off-by: Florian Koeberle <florianskarten@web.de>\n---\n .../jgit/errors/NoGitRepositoryFoundException.java |   65 ++++++++++++++++++++\n 1 files changed, 65 insertions(+), 0 deletions(-)\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/errors/NoGitRepositoryFoundException.java\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/errors/NoGitRepositoryFoundException.java b/org.spearce.jgit/src/org/spearce/jgit/errors/NoGitRepositoryFoundException.java\nnew file mode 100644\nindex 0000000..1d84e60\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/errors/NoGitRepositoryFoundException.java\n@@ -0,0 +1,65 @@\n+/*\n+ * Copyright (C) 2008, Florian KÃ¶berle <florianskarten@web.de>\n+ *\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or\n+ * without modification, are permitted provided that the following\n+ * conditions are met:\n+ *\n+ * - Redistributions of source code must retain the above copyright\n+ *   notice, this list of conditions and the following disclaimer.\n+ *\n+ * - Redistributions in binary form must reproduce the above\n+ *   copyright notice, this list of conditions and the following\n+ *   disclaimer in the documentation and/or other materials provided\n+ *   with the distribution.\n+ *\n+ * - Neither the name of the Git Development Community nor the\n+ *   names of its contributors may be used to endorse or promote\n+ *   products derived from this software without specific prior\n+ *   written permission.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n+ * CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+package org.spearce.jgit.errors;\n+\n+import java.io.File;\n+\n+/**\n+ * No git repository could be found for a file or directory.\n+ */\n+public class NoGitRepositoryFoundException extends Exception {\n+\tprivate final File fileWeSearchedRepositoryFor;\n+\n+\t/**\n+\t * @param fileWeSearchedRepositoryFor\n+\t *            the file for which a repository was searched.\n+\t */\n+\tpublic NoGitRepositoryFoundException(final File fileWeSearchedRepositoryFor) {\n+\t\tsuper(String.format(\"No repository found for file '%s'\",\n+\t\t\t\tfileWeSearchedRepositoryFor));\n+\t\tthis.fileWeSearchedRepositoryFor = fileWeSearchedRepositoryFor;\n+\t}\n+\n+\t/**\n+\t * @return the file searched for.\n+\t */\n+\tpublic File getFileWeSearchedRepositoryFor() {\n+\t\treturn fileWeSearchedRepositoryFor;\n+\t}\n+\n+}\n-- \n1.5.4.3\n"},{"id":"79757","messageId":"1213382121-19786-20-git-send-email-florianskarten@web.de","threadId":"13934","inReplyTo":"4852BCCA.4030404@web.de","subject":"[JGIT PATCH v4 20/24] Formatted Repository class.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-06-13T18:35:17Z","receivedAt":"2008-06-13T18:35:17Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Signed-off-by: Florian Koeberle <florianskarten@web.de>\n---\n .../src/org/spearce/jgit/lib/Repository.java       |  285 +++++++++++---------\n 1 files changed, 160 insertions(+), 125 deletions(-)\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java\nindex 5a21c6e..d7c3b13 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java\n@@ -66,16 +66,17 @@ import org.spearce.jgit.util.FS;\n  *\n  * <ul>\n  * <li>GIT_DIR\n- * \t<ul>\n- * \t\t<li>objects/ - objects</li>\n- * \t\t<li>refs/ - tags and heads</li>\n- * \t\t<li>config - configuration</li>\n- * \t\t<li>info/ - more configurations</li>\n- * \t</ul>\n+ * <ul>\n+ * <li>objects/ - objects</li>\n+ * <li>refs/ - tags and heads</li>\n+ * <li>config - configuration</li>\n+ * <li>info/ - more configurations</li>\n+ * </ul>\n  * </li>\n  * </ul>\n  *\n- * This implementation only handles a subtly undocumented subset of git features.\n+ * This implementation only handles a subtly undocumented subset of git\n+ * features.\n  *\n  */\n public class Repository {\n@@ -93,7 +94,7 @@ public class Repository {\n \n \t/**\n \t * Construct a representation of a Git repository.\n-\t * \n+\t *\n \t * @param d\n \t *            GIT_DIR (the location of the repository metadata).\n \t * @throws IOException\n@@ -106,7 +107,8 @@ public class Repository {\n \t\t\tobjectsDirs = readObjectsDirs(FS.resolve(gitDir, \"objects\"),\n \t\t\t\t\tnew ArrayList<File>()).toArray(new File[0]);\n \t\t} catch (IOException e) {\n-\t\t\tIOException ex = new IOException(\"Cannot find all object dirs for \" + gitDir);\n+\t\t\tIOException ex = new IOException(\"Cannot find all object dirs for \"\n+\t\t\t\t\t+ gitDir);\n \t\t\tex.initCause(e);\n \t\t\tthrow ex;\n \t\t}\n@@ -130,12 +132,13 @@ public class Repository {\n \t\t\tscanForPacks();\n \t}\n \n-\tprivate Collection<File> readObjectsDirs(File objectsDir, Collection<File> ret) throws IOException {\n+\tprivate Collection<File> readObjectsDirs(File objectsDir,\n+\t\t\tCollection<File> ret) throws IOException {\n \t\tret.add(objectsDir);\n \t\tfinal File altFile = FS.resolve(objectsDir, \"info/alternates\");\n \t\tif (altFile.exists()) {\n \t\t\tBufferedReader ar = new BufferedReader(new FileReader(altFile));\n-\t\t\tfor (String alt=ar.readLine(); alt!=null; alt=ar.readLine()) {\n+\t\t\tfor (String alt = ar.readLine(); alt != null; alt = ar.readLine()) {\n \t\t\t\treadObjectsDirs(FS.resolve(objectsDir, alt), ret);\n \t\t\t}\n \t\t\tar.close();\n@@ -204,9 +207,9 @@ public class Repository {\n \t */\n \tpublic File toFile(final AnyObjectId objectId) {\n \t\tfinal String n = objectId.toString();\n-\t\tString d=n.substring(0, 2);\n-\t\tString f=n.substring(2);\n-\t\tfor (int i=0; i<objectsDirs.length; ++i) {\n+\t\tString d = n.substring(0, 2);\n+\t\tString f = n.substring(2);\n+\t\tfor (int i = 0; i < objectsDirs.length; ++i) {\n \t\t\tFile ret = new File(new File(objectsDirs[i], d), f);\n \t\t\tif (ret.exists())\n \t\t\t\treturn ret;\n@@ -233,14 +236,13 @@ public class Repository {\n \t/**\n \t * @param id\n \t *            SHA-1 of an object.\n-\t * \n+\t *\n \t * @return a {@link ObjectLoader} for accessing the data of the named\n \t *         object, or null if the object does not exist.\n \t * @throws IOException\n \t */\n-\tpublic ObjectLoader openObject(final AnyObjectId id)\n-\t\t\tthrows IOException {\n-\t\treturn openObject(new WindowCursor(),id);\n+\tpublic ObjectLoader openObject(final AnyObjectId id) throws IOException {\n+\t\treturn openObject(new WindowCursor(), id);\n \t}\n \n \t/**\n@@ -248,7 +250,7 @@ public class Repository {\n \t *            temporary working space associated with the calling thread.\n \t * @param id\n \t *            SHA-1 of an object.\n-\t * \n+\t *\n \t * @return a {@link ObjectLoader} for accessing the data of the named\n \t *         object, or null if the object does not exist.\n \t * @throws IOException\n@@ -266,7 +268,8 @@ public class Repository {\n \t\t\t\t\t// This shouldn't happen unless the pack was corrupted\n \t\t\t\t\t// after we opened it or the VM runs out of memory. This is\n \t\t\t\t\t// a know problem with memory mapped I/O in java and have\n-\t\t\t\t\t// been noticed with JDK < 1.6. Tell the gc that now is a good\n+\t\t\t\t\t// been noticed with JDK < 1.6. Tell the gc that now is a\n+\t\t\t\t\t// good\n \t\t\t\t\t// time to collect and try once more.\n \t\t\t\t\ttry {\n \t\t\t\t\t\tcurs.release();\n@@ -312,13 +315,15 @@ public class Repository {\n \t}\n \n \t/**\n-\t * Access a Commit object using a symbolic reference. This reference may\n-\t * be a SHA-1 or ref in combination with a number of symbols translating\n-\t * from one ref or SHA1-1 to another, such as HEAD^ etc.\n+\t * Access a Commit object using a symbolic reference. This reference may be\n+\t * a SHA-1 or ref in combination with a number of symbols translating from\n+\t * one ref or SHA1-1 to another, such as HEAD^ etc.\n \t *\n-\t * @param revstr a reference to a git commit object\n+\t * @param revstr\n+\t *            a reference to a git commit object\n \t * @return a Commit named by the specified string\n-\t * @throws IOException for I/O error or unexpected object type.\n+\t * @throws IOException\n+\t *             for I/O error or unexpected object type.\n \t *\n \t * @see #resolve(String)\n \t */\n@@ -332,11 +337,13 @@ public class Repository {\n \t *\n \t * @param id\n \t *            SHA-1 of object to read\n-\t * @param refName optional, only relevant for simple tags\n+\t * @param refName\n+\t *            optional, only relevant for simple tags\n \t * @return The Git object if found or null\n \t * @throws IOException\n \t */\n-\tpublic Object mapObject(final ObjectId id, final String refName) throws IOException {\n+\tpublic Object mapObject(final ObjectId id, final String refName)\n+\t\t\tthrows IOException {\n \t\tfinal ObjectLoader or = openObject(id);\n \t\tfinal byte[] raw = or.getBytes();\n \t\tif (or.getType() == Constants.OBJ_TREE)\n@@ -352,9 +359,11 @@ public class Repository {\n \n \t/**\n \t * Access a Commit by SHA'1 id.\n+\t *\n \t * @param id\n \t * @return Commit or null\n-\t * @throws IOException for I/O error or unexpected object type.\n+\t * @throws IOException\n+\t *             for I/O error or unexpected object type.\n \t */\n \tpublic Commit mapCommit(final ObjectId id) throws IOException {\n \t\tfinal ObjectLoader or = openObject(id);\n@@ -372,11 +381,12 @@ public class Repository {\n \t}\n \n \t/**\n-\t * Access a Tree object using a symbolic reference. This reference may\n-\t * be a SHA-1 or ref in combination with a number of symbols translating\n-\t * from one ref or SHA1-1 to another, such as HEAD^{tree} etc.\n+\t * Access a Tree object using a symbolic reference. This reference may be a\n+\t * SHA-1 or ref in combination with a number of symbols translating from one\n+\t * ref or SHA1-1 to another, such as HEAD^{tree} etc.\n \t *\n-\t * @param revstr a reference to a git commit object\n+\t * @param revstr\n+\t *            a reference to a git commit object\n \t * @return a Tree named by the specified string\n \t * @throws IOException\n \t *\n@@ -389,9 +399,11 @@ public class Repository {\n \n \t/**\n \t * Access a Tree by SHA'1 id.\n+\t *\n \t * @param id\n \t * @return Tree or null\n-\t * @throws IOException for I/O error or unexpected object type.\n+\t * @throws IOException\n+\t *             for I/O error or unexpected object type.\n \t */\n \tpublic Tree mapTree(final ObjectId id) throws IOException {\n \t\tfinal ObjectLoader or = openObject(id);\n@@ -406,12 +418,14 @@ public class Repository {\n \t\tthrow new IncorrectObjectTypeException(id, Constants.TYPE_TREE);\n \t}\n \n-\tprivate Tree makeTree(final ObjectId id, final byte[] raw) throws IOException {\n+\tprivate Tree makeTree(final ObjectId id, final byte[] raw)\n+\t\t\tthrows IOException {\n \t\tTree ret = new Tree(this, id, raw);\n \t\treturn ret;\n \t}\n \n-\tprivate Tag makeTag(final ObjectId id, final String refName, final byte[] raw) {\n+\tprivate Tag makeTag(final ObjectId id, final String refName,\n+\t\t\tfinal byte[] raw) {\n \t\tTag ret = new Tag(this, id, refName, raw);\n \t\treturn ret;\n \t}\n@@ -421,7 +435,8 @@ public class Repository {\n \t *\n \t * @param revstr\n \t * @return a Tag or null\n-\t * @throws IOException on I/O error or unexpected type\n+\t * @throws IOException\n+\t *             on I/O error or unexpected type\n \t */\n \tpublic Tag mapTag(String revstr) throws IOException {\n \t\tfinal ObjectId id = resolve(revstr);\n@@ -430,12 +445,15 @@ public class Repository {\n \n \t/**\n \t * Access a Tag by SHA'1 id\n+\t *\n \t * @param refName\n \t * @param id\n \t * @return Commit or null\n-\t * @throws IOException for I/O error or unexpected object type.\n+\t * @throws IOException\n+\t *             for I/O error or unexpected object type.\n \t */\n-\tpublic Tag mapTag(final String refName, final ObjectId id) throws IOException {\n+\tpublic Tag mapTag(final String refName, final ObjectId id)\n+\t\t\tthrows IOException {\n \t\tfinal ObjectLoader or = openObject(id);\n \t\tif (or == null)\n \t\t\treturn null;\n@@ -447,7 +465,7 @@ public class Repository {\n \n \t/**\n \t * Create a command to update (or create) a ref in this repository.\n-\t * \n+\t *\n \t * @param ref\n \t *            name of the ref the caller wants to modify.\n \t * @return an update command. The caller must finish populating this command\n@@ -466,13 +484,13 @@ public class Repository {\n \t *\n \t * Currently supported is combinations of these.\n \t * <ul>\n-\t *  <li>SHA-1 - a SHA-1</li>\n-\t *  <li>refs/... - a ref name</li>\n-\t *  <li>ref^n - nth parent reference</li>\n-\t *  <li>ref~n - distance via parent reference</li>\n-\t *  <li>ref@{n} - nth version of ref</li>\n-\t *  <li>ref^{tree} - tree references by ref</li>\n-\t *  <li>ref^{commit} - commit references by ref</li>\n+\t * <li>SHA-1 - a SHA-1</li>\n+\t * <li>refs/... - a ref name</li>\n+\t * <li>ref^n - nth parent reference</li>\n+\t * <li>ref~n - distance via parent reference</li>\n+\t * <li>ref@{n} - nth version of ref</li>\n+\t * <li>ref^{tree} - tree references by ref</li>\n+\t * <li>ref^{commit} - commit references by ref</li>\n \t * </ul>\n \t *\n \t * Not supported is\n@@ -481,9 +499,11 @@ public class Repository {\n \t * <li>abbreviated SHA-1's</li>\n \t * </ul>\n \t *\n-\t * @param revstr A git object references expression\n+\t * @param revstr\n+\t *            A git object references expression\n \t * @return an ObjectId\n-\t * @throws IOException on serious errors\n+\t * @throws IOException\n+\t *             on serious errors\n \t */\n \tpublic ObjectId resolve(final String revstr) throws IOException {\n \t\tchar[] rev = revstr.toCharArray();\n@@ -493,7 +513,7 @@ public class Repository {\n \t\t\tswitch (rev[i]) {\n \t\t\tcase '^':\n \t\t\t\tif (refId == null) {\n-\t\t\t\t\tString refstr = new String(rev,0,i);\n+\t\t\t\t\tString refstr = new String(rev, 0, i);\n \t\t\t\t\trefId = resolveSimple(refstr);\n \t\t\t\t\tif (refId == null)\n \t\t\t\t\t\treturn null;\n@@ -513,23 +533,24 @@ public class Repository {\n \t\t\t\t\t\tint j;\n \t\t\t\t\t\tref = mapObject(refId, null);\n \t\t\t\t\t\tif (!(ref instanceof Commit))\n-\t\t\t\t\t\t\tthrow new IncorrectObjectTypeException(refId, Constants.TYPE_COMMIT);\n-\t\t\t\t\t\tfor (j=i+1; j<rev.length; ++j) {\n+\t\t\t\t\t\t\tthrow new IncorrectObjectTypeException(refId,\n+\t\t\t\t\t\t\t\t\tConstants.TYPE_COMMIT);\n+\t\t\t\t\t\tfor (j = i + 1; j < rev.length; ++j) {\n \t\t\t\t\t\t\tif (!Character.isDigit(rev[j]))\n \t\t\t\t\t\t\t\tbreak;\n \t\t\t\t\t\t}\n-\t\t\t\t\t\tString parentnum = new String(rev, i+1, j-i-1);\n+\t\t\t\t\t\tString parentnum = new String(rev, i + 1, j - i - 1);\n \t\t\t\t\t\tint pnum = Integer.parseInt(parentnum);\n \t\t\t\t\t\tif (pnum != 0)\n-\t\t\t\t\t\t\trefId = ((Commit)ref).getParentIds()[pnum - 1];\n+\t\t\t\t\t\t\trefId = ((Commit) ref).getParentIds()[pnum - 1];\n \t\t\t\t\t\ti = j - 1;\n \t\t\t\t\t\tbreak;\n \t\t\t\t\tcase '{':\n \t\t\t\t\t\tint k;\n \t\t\t\t\t\tString item = null;\n-\t\t\t\t\t\tfor (k=i+2; k<rev.length; ++k) {\n+\t\t\t\t\t\tfor (k = i + 2; k < rev.length; ++k) {\n \t\t\t\t\t\t\tif (rev[k] == '}') {\n-\t\t\t\t\t\t\t\titem = new String(rev, i+2, k-i-2);\n+\t\t\t\t\t\t\t\titem = new String(rev, i + 2, k - i - 2);\n \t\t\t\t\t\t\t\tbreak;\n \t\t\t\t\t\t\t}\n \t\t\t\t\t\t}\n@@ -538,44 +559,43 @@ public class Repository {\n \t\t\t\t\t\t\tif (item.equals(\"tree\")) {\n \t\t\t\t\t\t\t\tref = mapObject(refId, null);\n \t\t\t\t\t\t\t\twhile (ref instanceof Tag) {\n-\t\t\t\t\t\t\t\t\tTag t = (Tag)ref;\n+\t\t\t\t\t\t\t\t\tTag t = (Tag) ref;\n \t\t\t\t\t\t\t\t\trefId = t.getObjId();\n \t\t\t\t\t\t\t\t\tref = mapObject(refId, null);\n \t\t\t\t\t\t\t\t}\n \t\t\t\t\t\t\t\tif (ref instanceof Treeish)\n-\t\t\t\t\t\t\t\t\trefId = ((Treeish)ref).getTreeId();\n+\t\t\t\t\t\t\t\t\trefId = ((Treeish) ref).getTreeId();\n \t\t\t\t\t\t\t\telse\n-\t\t\t\t\t\t\t\t\tthrow new IncorrectObjectTypeException(refId,  Constants.TYPE_TREE);\n-\t\t\t\t\t\t\t}\n-\t\t\t\t\t\t\telse if (item.equals(\"commit\")) {\n+\t\t\t\t\t\t\t\t\tthrow new IncorrectObjectTypeException(\n+\t\t\t\t\t\t\t\t\t\t\trefId, Constants.TYPE_TREE);\n+\t\t\t\t\t\t\t} else if (item.equals(\"commit\")) {\n \t\t\t\t\t\t\t\tref = mapObject(refId, null);\n \t\t\t\t\t\t\t\twhile (ref instanceof Tag) {\n-\t\t\t\t\t\t\t\t\tTag t = (Tag)ref;\n+\t\t\t\t\t\t\t\t\tTag t = (Tag) ref;\n \t\t\t\t\t\t\t\t\trefId = t.getObjId();\n \t\t\t\t\t\t\t\t\tref = mapObject(refId, null);\n \t\t\t\t\t\t\t\t}\n \t\t\t\t\t\t\t\tif (!(ref instanceof Commit))\n-\t\t\t\t\t\t\t\t\tthrow new IncorrectObjectTypeException(refId,  Constants.TYPE_COMMIT);\n-\t\t\t\t\t\t\t}\n-\t\t\t\t\t\t\telse if (item.equals(\"blob\")) {\n+\t\t\t\t\t\t\t\t\tthrow new IncorrectObjectTypeException(\n+\t\t\t\t\t\t\t\t\t\t\trefId, Constants.TYPE_COMMIT);\n+\t\t\t\t\t\t\t} else if (item.equals(\"blob\")) {\n \t\t\t\t\t\t\t\tref = mapObject(refId, null);\n \t\t\t\t\t\t\t\twhile (ref instanceof Tag) {\n-\t\t\t\t\t\t\t\t\tTag t = (Tag)ref;\n+\t\t\t\t\t\t\t\t\tTag t = (Tag) ref;\n \t\t\t\t\t\t\t\t\trefId = t.getObjId();\n \t\t\t\t\t\t\t\t\tref = mapObject(refId, null);\n \t\t\t\t\t\t\t\t}\n \t\t\t\t\t\t\t\tif (!(ref instanceof byte[]))\n-\t\t\t\t\t\t\t\t\tthrow new IncorrectObjectTypeException(refId,  Constants.TYPE_COMMIT);\n-\t\t\t\t\t\t\t}\n-\t\t\t\t\t\t\telse if (item.equals(\"\")) {\n+\t\t\t\t\t\t\t\t\tthrow new IncorrectObjectTypeException(\n+\t\t\t\t\t\t\t\t\t\t\trefId, Constants.TYPE_COMMIT);\n+\t\t\t\t\t\t\t} else if (item.equals(\"\")) {\n \t\t\t\t\t\t\t\tref = mapObject(refId, null);\n \t\t\t\t\t\t\t\tif (ref instanceof Tag)\n-\t\t\t\t\t\t\t\t\trefId = ((Tag)ref).getObjId();\n+\t\t\t\t\t\t\t\t\trefId = ((Tag) ref).getObjId();\n \t\t\t\t\t\t\t\telse {\n \t\t\t\t\t\t\t\t\t// self\n \t\t\t\t\t\t\t\t}\n-\t\t\t\t\t\t\t}\n-\t\t\t\t\t\t\telse\n+\t\t\t\t\t\t\t} else\n \t\t\t\t\t\t\t\tthrow new RevisionSyntaxException(revstr);\n \t\t\t\t\t\telse\n \t\t\t\t\t\t\tthrow new RevisionSyntaxException(revstr);\n@@ -583,22 +603,24 @@ public class Repository {\n \t\t\t\t\tdefault:\n \t\t\t\t\t\tref = mapObject(refId, null);\n \t\t\t\t\t\tif (ref instanceof Commit)\n-\t\t\t\t\t\t\trefId = ((Commit)ref).getParentIds()[0];\n+\t\t\t\t\t\t\trefId = ((Commit) ref).getParentIds()[0];\n \t\t\t\t\t\telse\n-\t\t\t\t\t\t\tthrow new IncorrectObjectTypeException(refId,  Constants.TYPE_COMMIT);\n-\t\t\t\t\t\t\n+\t\t\t\t\t\t\tthrow new IncorrectObjectTypeException(refId,\n+\t\t\t\t\t\t\t\t\tConstants.TYPE_COMMIT);\n+\n \t\t\t\t\t}\n \t\t\t\t} else {\n \t\t\t\t\tref = mapObject(refId, null);\n \t\t\t\t\tif (ref instanceof Commit)\n-\t\t\t\t\t\trefId = ((Commit)ref).getParentIds()[0];\n+\t\t\t\t\t\trefId = ((Commit) ref).getParentIds()[0];\n \t\t\t\t\telse\n-\t\t\t\t\t\tthrow new IncorrectObjectTypeException(refId,  Constants.TYPE_COMMIT);\n+\t\t\t\t\t\tthrow new IncorrectObjectTypeException(refId,\n+\t\t\t\t\t\t\t\tConstants.TYPE_COMMIT);\n \t\t\t\t}\n \t\t\t\tbreak;\n \t\t\tcase '~':\n \t\t\t\tif (ref == null) {\n-\t\t\t\t\tString refstr = new String(rev,0,i);\n+\t\t\t\t\tString refstr = new String(rev, 0, i);\n \t\t\t\t\trefId = resolveSimple(refstr);\n \t\t\t\t\tref = mapCommit(refId);\n \t\t\t\t}\n@@ -607,10 +629,10 @@ public class Repository {\n \t\t\t\t\tif (!Character.isDigit(rev[l]))\n \t\t\t\t\t\tbreak;\n \t\t\t\t}\n-\t\t\t\tString distnum = new String(rev, i+1, l-i-1);\n+\t\t\t\tString distnum = new String(rev, i + 1, l - i - 1);\n \t\t\t\tint dist = Integer.parseInt(distnum);\n \t\t\t\twhile (dist >= 0) {\n-\t\t\t\t\trefId = ((Commit)ref).getParentIds()[0];\n+\t\t\t\t\trefId = ((Commit) ref).getParentIds()[0];\n \t\t\t\t\tref = mapCommit(refId);\n \t\t\t\t\t--dist;\n \t\t\t\t}\n@@ -619,14 +641,16 @@ public class Repository {\n \t\t\tcase '@':\n \t\t\t\tint m;\n \t\t\t\tString time = null;\n-\t\t\t\tfor (m=i+2; m<rev.length; ++m) {\n+\t\t\t\tfor (m = i + 2; m < rev.length; ++m) {\n \t\t\t\t\tif (rev[m] == '}') {\n-\t\t\t\t\t\ttime = new String(rev, i+2, m-i-2);\n+\t\t\t\t\t\ttime = new String(rev, i + 2, m - i - 2);\n \t\t\t\t\t\tbreak;\n \t\t\t\t\t}\n \t\t\t\t}\n \t\t\t\tif (time != null)\n-\t\t\t\t\tthrow new RevisionSyntaxException(\"reflogs not yet supported by revision parser yet\", revstr);\n+\t\t\t\t\tthrow new RevisionSyntaxException(\n+\t\t\t\t\t\t\t\"reflogs not yet supported by revision parser yet\",\n+\t\t\t\t\t\t\trevstr);\n \t\t\t\ti = m - 1;\n \t\t\t\tbreak;\n \t\t\tdefault:\n@@ -662,7 +686,7 @@ public class Repository {\n \n \t/**\n \t * Add a single existing pack to the list of available pack files.\n-\t * \n+\t *\n \t * @param pack\n \t *            path of the pack file to open.\n \t * @param idx\n@@ -675,10 +699,10 @@ public class Repository {\n \t\tfinal String p = pack.getName();\n \t\tfinal String i = idx.getName();\n \t\tif (p.length() != 50 || !p.startsWith(\"pack-\") || !p.endsWith(\".pack\"))\n-\t\t    throw new IllegalArgumentException(\"Not a valid pack \" + pack);\n+\t\t\tthrow new IllegalArgumentException(\"Not a valid pack \" + pack);\n \t\tif (i.length() != 49 || !i.startsWith(\"pack-\") || !i.endsWith(\".idx\"))\n-\t\t    throw new IllegalArgumentException(\"Not a valid pack \" + idx);\n-\t\tif (!p.substring(0,45).equals(i.substring(0,45)))\n+\t\t\tthrow new IllegalArgumentException(\"Not a valid pack \" + idx);\n+\t\tif (!p.substring(0, 45).equals(i.substring(0, 45)))\n \t\t\tthrow new IllegalArgumentException(\"Pack \" + pack\n \t\t\t\t\t+ \"does not match index \" + idx);\n \n@@ -690,12 +714,11 @@ public class Repository {\n \t}\n \n \t/**\n-\t * Scan the object dirs, including alternates for packs\n-\t * to use.\n+\t * Scan the object dirs, including alternates for packs to use.\n \t */\n \tpublic void scanForPacks() {\n \t\tfinal ArrayList<PackFile> p = new ArrayList<PackFile>();\n-\t\tfor (int i=0; i<objectsDirs.length; ++i)\n+\t\tfor (int i = 0; i < objectsDirs.length; ++i)\n \t\t\tscanForPacks(new File(objectsDirs[i], \"pack\"), p);\n \t\tfinal PackFile[] arr = new PackFile[p.size()];\n \t\tp.toArray(arr);\n@@ -735,14 +758,16 @@ public class Repository {\n \t\t}\n \t}\n \n-    /**\n-     * Writes a symref (e.g. HEAD) to disk\n-     *\n-     * @param name symref name\n-     * @param target pointed to ref\n-     * @throws IOException\n-     */\n-    public void writeSymref(final String name, final String target)\n+\t/**\n+\t * Writes a symref (e.g. HEAD) to disk\n+\t *\n+\t * @param name\n+\t *            symref name\n+\t * @param target\n+\t *            pointed to ref\n+\t * @throws IOException\n+\t */\n+\tpublic void writeSymref(final String name, final String target)\n \t\t\tthrows IOException {\n \t\trefs.link(name, target);\n \t}\n@@ -756,12 +781,13 @@ public class Repository {\n \t * @throws IOException\n \t */\n \tpublic String getPatch() throws IOException {\n-\t\tfinal File ptr = new File(getDirectory(),\"patches/\"+getBranch()+\"/applied\");\n+\t\tfinal File ptr = new File(getDirectory(), \"patches/\" + getBranch()\n+\t\t\t\t+ \"/applied\");\n \t\tfinal BufferedReader br = new BufferedReader(new FileReader(ptr));\n-\t\tString last=null;\n+\t\tString last = null;\n \t\ttry {\n \t\t\tString line;\n-\t\t\twhile ((line=br.readLine())!=null) {\n+\t\t\twhile ((line = br.readLine()) != null) {\n \t\t\t\tlast = line;\n \t\t\t}\n \t\t} finally {\n@@ -775,7 +801,7 @@ public class Repository {\n \t * @throws IOException\n \t */\n \tpublic String getFullBranch() throws IOException {\n-\t\tfinal File ptr = new File(getDirectory(),\"HEAD\");\n+\t\tfinal File ptr = new File(getDirectory(), \"HEAD\");\n \t\tfinal BufferedReader br = new BufferedReader(new FileReader(ptr));\n \t\tString ref;\n \t\ttry {\n@@ -787,7 +813,7 @@ public class Repository {\n \t\t\tref = ref.substring(5);\n \t\treturn ref;\n \t}\n-\t\n+\n \t/**\n \t * @return name of current branch.\n \t * @throws IOException\n@@ -808,7 +834,7 @@ public class Repository {\n \t\t\t\tref = ref.substring(11);\n \t\t\treturn ref;\n \t\t} catch (FileNotFoundException e) {\n-\t\t\tfinal File ptr = new File(getDirectory(),\"head-name\");\n+\t\t\tfinal File ptr = new File(getDirectory(), \"head-name\");\n \t\t\tfinal BufferedReader br = new BufferedReader(new FileReader(ptr));\n \t\t\tString ref;\n \t\t\ttry {\n@@ -819,7 +845,7 @@ public class Repository {\n \t\t\treturn ref;\n \t\t}\n \t}\n-\t\n+\n \t/**\n \t * @return all known refs (heads, tags, remotes).\n \t */\n@@ -864,13 +890,17 @@ public class Repository {\n \t * @return applied patches in a map indexed on current commit id\n \t * @throws IOException\n \t */\n-\tpublic Map<ObjectId,StGitPatch> getAppliedPatches() throws IOException {\n-\t\tMap<ObjectId,StGitPatch> ret = new HashMap<ObjectId,StGitPatch>();\n+\tpublic Map<ObjectId, StGitPatch> getAppliedPatches() throws IOException {\n+\t\tMap<ObjectId, StGitPatch> ret = new HashMap<ObjectId, StGitPatch>();\n \t\tif (isStGitMode()) {\n-\t\t\tFile patchDir = new File(new File(getDirectory(),\"patches\"),getBranch());\n-\t\t\tBufferedReader apr = new BufferedReader(new FileReader(new File(patchDir,\"applied\")));\n-\t\t\tfor (String patchName=apr.readLine(); patchName!=null; patchName=apr.readLine()) {\n-\t\t\t\tFile topFile = new File(new File(new File(patchDir,\"patches\"), patchName), \"top\");\n+\t\t\tFile patchDir = new File(new File(getDirectory(), \"patches\"),\n+\t\t\t\t\tgetBranch());\n+\t\t\tBufferedReader apr = new BufferedReader(new FileReader(new File(\n+\t\t\t\t\tpatchDir, \"applied\")));\n+\t\t\tfor (String patchName = apr.readLine(); patchName != null; patchName = apr\n+\t\t\t\t\t.readLine()) {\n+\t\t\t\tFile topFile = new File(new File(new File(patchDir, \"patches\"),\n+\t\t\t\t\t\tpatchName), \"top\");\n \t\t\t\tBufferedReader tfr = new BufferedReader(new FileReader(topFile));\n \t\t\t\tString objectId = tfr.readLine();\n \t\t\t\tObjectId id = ObjectId.fromString(objectId);\n@@ -881,7 +911,7 @@ public class Repository {\n \t\t}\n \t\treturn ret;\n \t}\n-\t\n+\n \t/** Clean up stale caches */\n \tpublic void refreshFromDisk() {\n \t\trefs.clearCache();\n@@ -904,7 +934,7 @@ public class Repository {\n \tstatic byte[] gitInternalSlash(byte[] bytes) {\n \t\tif (File.separatorChar == '/')\n \t\t\treturn bytes;\n-\t\tfor (int i=0; i<bytes.length; ++i)\n+\t\tfor (int i = 0; i < bytes.length; ++i)\n \t\t\tif (bytes[i] == File.separatorChar)\n \t\t\t\tbytes[i] = '/';\n \t\treturn bytes;\n@@ -916,18 +946,18 @@ public class Repository {\n \tpublic RepositoryState getRepositoryState() {\n \t\tif (new File(getWorkDir(), \".dotest\").exists())\n \t\t\treturn RepositoryState.REBASING;\n-\t\tif (new File(gitDir,\".dotest-merge\").exists())\n+\t\tif (new File(gitDir, \".dotest-merge\").exists())\n \t\t\treturn RepositoryState.REBASING_INTERACTIVE;\n-\t\tif (new File(gitDir,\"MERGE_HEAD\").exists())\n+\t\tif (new File(gitDir, \"MERGE_HEAD\").exists())\n \t\t\treturn RepositoryState.MERGING;\n-\t\tif (new File(gitDir,\"BISECT_LOG\").exists())\n+\t\tif (new File(gitDir, \"BISECT_LOG\").exists())\n \t\t\treturn RepositoryState.BISECTING;\n \t\treturn RepositoryState.SAFE;\n \t}\n \n \t/**\n-\t * Check validty of a ref name. It must not contain character that has\n-\t * a special meaning in a Git object reference expression. Some other\n+\t * Check validty of a ref name. It must not contain character that has a\n+\t * special meaning in a Git object reference expression. Some other\n \t * dangerous characters are also excluded.\n \t *\n \t * @param refName\n@@ -937,11 +967,11 @@ public class Repository {\n \tpublic static boolean isValidRefName(final String refName) {\n \t\tfinal int len = refName.length();\n \t\tchar p = '\\0';\n-\t\tfor (int i=0; i<len; ++i) {\n+\t\tfor (int i = 0; i < len; ++i) {\n \t\t\tchar c = refName.charAt(i);\n \t\t\tif (c <= ' ')\n \t\t\t\treturn false;\n-\t\t\tswitch(c) {\n+\t\t\tswitch (c) {\n \t\t\tcase '.':\n \t\t\t\tif (i == 0)\n \t\t\t\t\treturn false;\n@@ -953,11 +983,14 @@ public class Repository {\n \t\t\tcase '/':\n \t\t\t\tif (i == 0)\n \t\t\t\t\treturn false;\n-\t\t\t\tif (i == len -1)\n+\t\t\t\tif (i == len - 1)\n \t\t\t\t\treturn false;\n \t\t\t\tbreak;\n-\t\t\tcase '~': case '^': case ':':\n-\t\t\tcase '?': case '[':\n+\t\t\tcase '~':\n+\t\t\tcase '^':\n+\t\t\tcase ':':\n+\t\t\tcase '?':\n+\t\t\tcase '[':\n \t\t\t\treturn false;\n \t\t\tcase '*':\n \t\t\t\treturn false;\n@@ -970,8 +1003,10 @@ public class Repository {\n \t/**\n \t * String work dir and return normalized repository path\n \t *\n-\t * @param wd Work dir\n-\t * @param f File whose path shall be stripp off it's workdir\n+\t * @param wd\n+\t *            Work dir\n+\t * @param f\n+\t *            File whose path shall be stripp off it's workdir\n \t * @return normalized repository relative path\n \t */\n \tpublic static String stripWorkDir(File wd, File f) {\n@@ -989,7 +1024,7 @@ public class Repository {\n \n \t/**\n \t * Creates a new {@link WorkTree} and initialize a repository for it.\n-\t * \n+\t *\n \t * @param workTreeDirectory\n \t *            the directory with the project files.\n \t * @return a new {@link WorkTree} with a new and open {@link Repository}.\n-- \n1.5.4.3\n"},{"id":"79768","messageId":"1213382121-19786-21-git-send-email-florianskarten@web.de","threadId":"13934","inReplyTo":"4852BCCA.4030404@web.de","subject":"[JGIT PATCH v4 21/24] Added findWorkTree method to Repository class.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-06-13T18:35:18Z","receivedAt":"2008-06-13T18:35:18Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Signed-off-by: Florian Koeberle <florianskarten@web.de>\n---\n .../src/org/spearce/jgit/lib/Repository.java       |   80 ++++++++++++++++++++\n 1 files changed, 80 insertions(+), 0 deletions(-)\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java\nindex d7c3b13..ee7bbe4 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java\n@@ -39,6 +39,11 @@\n \n package org.spearce.jgit.lib;\n \n+import static org.spearce.jgit.lib.Constants.HEAD;\n+import static org.spearce.jgit.lib.Constants.OBJECTS_DIRECTORY_NAME;\n+import static org.spearce.jgit.lib.Constants.REFS_DIRECTORY_NAME;\n+import static org.spearce.jgit.lib.Constants.REPOSITORY_DIRECTORY_NAME;\n+\n import java.io.BufferedReader;\n import java.io.File;\n import java.io.FileNotFoundException;\n@@ -51,6 +56,7 @@ import java.util.HashMap;\n import java.util.Map;\n \n import org.spearce.jgit.errors.IncorrectObjectTypeException;\n+import org.spearce.jgit.errors.NoGitRepositoryFoundException;\n import org.spearce.jgit.errors.RevisionSyntaxException;\n import org.spearce.jgit.stgit.StGitPatch;\n import org.spearce.jgit.util.FS;\n@@ -1052,4 +1058,78 @@ public class Repository {\n \t\t}\n \t}\n \n+\t/**\n+\t * Find the git repository for the current working directory.\n+\t *\n+\t * @return a {@link Repository}.\n+\t * @throws NoGitRepositoryFoundException\n+\t *             if no git repository could be found for the current\n+\t *             directory.\n+\t * @throws IOException\n+\t *             if not able to determine the absolute path of the current\n+\t *             working directory.\n+\t */\n+\tpublic static WorkTree findWorkTree() throws NoGitRepositoryFoundException,\n+\t\t\tIOException {\n+\t\treturn findWorkTree(new File(\".\"));\n+\t}\n+\n+\t/**\n+\t * Checks if a path is a valid git repository. Works similar like the method\n+\t * is_git_directory from the original setup.c file.\n+\t *\n+\t * @param directory\n+\t *            the path which should be checked.\n+\t * @return true if the path is a valid git repository.\n+\t */\n+\tprivate static boolean isRepository(File directory) {\n+\t\tif (!directory.isDirectory()) {\n+\t\t\treturn false;\n+\t\t}\n+\n+\t\tfinal File objectDirectory = new File(directory, OBJECTS_DIRECTORY_NAME);\n+\t\tif (!objectDirectory.isDirectory()) {\n+\t\t\treturn false;\n+\t\t}\n+\n+\t\tfinal File refsDirectory = new File(directory, REFS_DIRECTORY_NAME);\n+\t\tif (!refsDirectory.isDirectory()) {\n+\t\t\treturn false;\n+\t\t}\n+\n+\t\tfinal File head = new File(directory, HEAD);\n+\t\tif (!hasValidateHeadRef(head)) {\n+\t\t\treturn false;\n+\t\t}\n+\n+\t\treturn true;\n+\t}\n+\n+\t/**\n+\t * Checks for example if a path is a valid HEAD file.\n+\t *\n+\t * @param path\n+\t *            is the path of the HEAD file.\n+\t * @return true if it has a valid head reference.\n+\t */\n+\tprivate static final boolean hasValidateHeadRef(File path) {\n+\t\treturn true; // TODO implement this method\n+\t}\n+\n+\tprivate static WorkTree findWorkTree(final File directory)\n+\t\t\tthrows IOException, NoGitRepositoryFoundException {\n+\t\tFile currentDirectory = directory.getAbsoluteFile();\n+\t\twhile (currentDirectory != null) {\n+\t\t\tfinal File commonGitDirectory = new File(directory,\n+\t\t\t\t\tREPOSITORY_DIRECTORY_NAME);\n+\t\t\tif (isRepository(commonGitDirectory))\n+\t\t\t\treturn new WorkTree(currentDirectory, new Repository(\n+\t\t\t\t\t\tcommonGitDirectory));\n+\t\t\tif (isRepository(currentDirectory))\n+\t\t\t\treturn new WorkTree(null, new Repository(currentDirectory));\n+\t\t\tcurrentDirectory = currentDirectory.getParentFile();\n+\t\t}\n+\t\tthrow new NoGitRepositoryFoundException(directory);\n+\t}\n+\n }\n-- \n1.5.4.3\n"},{"id":"79765","messageId":"1213382121-19786-22-git-send-email-florianskarten@web.de","threadId":"13934","inReplyTo":"4852BCCA.4030404@web.de","subject":"[JGIT PATCH v4 22/24] Formatted RepositoryTestCase.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-06-13T18:35:19Z","receivedAt":"2008-06-13T18:35:19Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Signed-off-by: Florian Koeberle <florianskarten@web.de>\n---\n .../org/spearce/jgit/lib/RepositoryTestCase.java   |   22 ++++++++++---------\n 1 files changed, 12 insertions(+), 10 deletions(-)\n\ndiff --git a/org.spearce.jgit.test/tst/org/spearce/jgit/lib/RepositoryTestCase.java b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/RepositoryTestCase.java\nindex 14e7179..aae9ed6 100644\n--- a/org.spearce.jgit.test/tst/org/spearce/jgit/lib/RepositoryTestCase.java\n+++ b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/RepositoryTestCase.java\n@@ -113,8 +113,8 @@ public abstract class RepositoryTestCase extends TestCase {\n \t\t\tthrows IOException {\n \t\tReader r = new InputStreamReader(new FileInputStream(f), \"ISO-8859-1\");\n \t\tchar[] data = new char[(int) f.length()];\n-\t\tif (f.length() !=  r.read(data))\n-\t\t\tthrow new IOException(\"Internal error reading file data from \"+f);\n+\t\tif (f.length() != r.read(data))\n+\t\t\tthrow new IOException(\"Internal error reading file data from \" + f);\n \t\tassertEquals(checkData, new String(data));\n \t}\n \n@@ -123,7 +123,7 @@ public abstract class RepositoryTestCase extends TestCase {\n \tpublic void setUp() throws Exception {\n \t\tsuper.setUp();\n \t\trecursiveDelete(trashParent);\n-\t\ttrash = new File(trashParent,\"trash\"+System.currentTimeMillis());\n+\t\ttrash = new File(trashParent, \"trash\" + System.currentTimeMillis());\n \t\ttrash_git = new File(trash, \".git\");\n \n \t\tRuntime.getRuntime().addShutdownHook(new Thread() {\n@@ -140,8 +140,7 @@ public abstract class RepositoryTestCase extends TestCase {\n \t\t\t\t\"pack-34be9032ac282b11fa9babdc2b2a93ca996c9c2f\",\n \t\t\t\t\"pack-df2982f284bbabb6bdb59ee3fcc6eb0983e20371\",\n \t\t\t\t\"pack-9fb5b411fe6dfa89cc2e6b89d2bd8e5de02b5745\",\n-\t\t\t\t\"pack-e6d07037cbcf13376308a0a995d1fa48f8f76aaa\"\n-\t\t};\n+\t\t\t\t\"pack-e6d07037cbcf13376308a0a995d1fa48f8f76aaa\" };\n \t\tfinal File tst = new File(\"tst\");\n \t\tfinal File packDir = new File(db.getObjectsDirectory(), \"pack\");\n \t\tfor (int k = 0; k < packs.length; k++) {\n@@ -151,7 +150,8 @@ public abstract class RepositoryTestCase extends TestCase {\n \t\t\t\t\tpacks[k] + \".idx\"));\n \t\t}\n \n-\t\tcopyFile(new File(tst, \"packed-refs\"), new File(trash_git,\"packed-refs\"));\n+\t\tcopyFile(new File(tst, \"packed-refs\"), new File(trash_git,\n+\t\t\t\t\"packed-refs\"));\n \n \t\tdb.scanForPacks();\n \t}\n@@ -163,15 +163,17 @@ public abstract class RepositoryTestCase extends TestCase {\n \n \t/**\n \t * Helper for creating extra empty repos\n-\t *\n+\t * \n \t * @return a new empty git repository for testing purposes\n-\t *\n+\t * \n \t * @throws IOException\n \t */\n \tprotected Repository createNewEmptyRepo() throws IOException {\n-\t\tFile newTestRepo = new File(trashParent, \"new\"+System.currentTimeMillis()+\"/.git\");\n+\t\tFile newTestRepo = new File(trashParent, \"new\"\n+\t\t\t\t+ System.currentTimeMillis() + \"/.git\");\n \t\tassertFalse(newTestRepo.exists());\n-\t\tFile unusedDir = new File(trashParent, \"tmp\"+System.currentTimeMillis());\n+\t\tFile unusedDir = new File(trashParent, \"tmp\"\n+\t\t\t\t+ System.currentTimeMillis());\n \t\tassertTrue(unusedDir.mkdirs());\n \t\tfinal Repository newRepo = new Repository(newTestRepo);\n \t\tnewRepo.create();\n-- \n1.5.4.3\n"},{"id":"79771","messageId":"1213382121-19786-23-git-send-email-florianskarten@web.de","threadId":"13934","inReplyTo":"4852BCCA.4030404@web.de","subject":"[JGIT PATCH v4 23/24] Added a super class for RepositoryTestCase with a createTemporaryDirectory() method.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-06-13T18:35:20Z","receivedAt":"2008-06-13T18:35:20Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Signed-off-by: Florian Koeberle <florianskarten@web.de>\n---\n .../tst/org/spearce/jgit/lib/AbstractTestCase.java |  108 ++++++++++++++++++++\n .../org/spearce/jgit/lib/RepositoryTestCase.java   |   22 +----\n 2 files changed, 109 insertions(+), 21 deletions(-)\n create mode 100644 org.spearce.jgit.test/tst/org/spearce/jgit/lib/AbstractTestCase.java\n\ndiff --git a/org.spearce.jgit.test/tst/org/spearce/jgit/lib/AbstractTestCase.java b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/AbstractTestCase.java\nnew file mode 100644\nindex 0000000..c017fc0\n--- /dev/null\n+++ b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/AbstractTestCase.java\n@@ -0,0 +1,108 @@\n+/*\n+ * Copyright (C) 2006,  Shawn Pearce <spearce@spearce.org>\n+ * Copyright (C) 2008, Florian KÃ¶berle <florianskarten@web.de>\n+ *\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or\n+ * without modification, are permitted provided that the following\n+ * conditions are met:\n+ *\n+ * - Redistributions of source code must retain the above copyright\n+ *   notice, this list of conditions and the following disclaimer.\n+ *\n+ * - Redistributions in binary form must reproduce the above\n+ *   copyright notice, this list of conditions and the following\n+ *   disclaimer in the documentation and/or other materials provided\n+ *   with the distribution.\n+ *\n+ * - Neither the name of the Git Development Community nor the\n+ *   names of its contributors may be used to endorse or promote\n+ *   products derived from this software without specific prior\n+ *   written permission.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n+ * CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+package org.spearce.jgit.lib;\n+\n+import java.io.File;\n+import java.io.IOException;\n+import java.util.Stack;\n+\n+import junit.framework.TestCase;\n+\n+/**\n+ * This class can be used as base testcase\n+ * \n+ */\n+public abstract class AbstractTestCase extends TestCase {\n+\tprivate final Stack<File> directoriesToDelete = new Stack<File>();\n+\n+\tprotected void setUp() throws Exception {\n+\t\tsuper.setUp();\n+\t\t// Do not delete directories from other test runs\n+\t\t// in order to avoid side effects between tests.\n+\t\tdirectoriesToDelete.clear();\n+\t}\n+\n+\t/**\n+\t * Creates a new directory for test purposes. The directory and it's content\n+\t * will be deleted when the test is over.\n+\t * \n+\t * @return a temporary directory for the use in one test.\n+\t * @throws IOException\n+\t *             if the creation of the temporary directory fails.\n+\t */\n+\tprotected File createTemporaryDirectory() throws IOException {\n+\t\tFile directory = null;\n+\t\tdo {\n+\t\t\tdirectory = File.createTempFile(\"test\", \"\");\n+\t\t\tif (!directory.delete())\n+\t\t\t\tthrow new IOException(\"can't delete temporary file\");\n+\n+\t\t\tif (!directory.mkdir())\n+\t\t\t\tdirectory = null;\n+\n+\t\t} while (directory == null);\n+\t\treturn directory;\n+\t}\n+\n+\tprotected static void recursiveDelete(final File dir) {\n+\t\tfinal File[] ls = dir.listFiles();\n+\t\tif (ls != null) {\n+\t\t\tfor (int k = 0; k < ls.length; k++) {\n+\t\t\t\tfinal File e = ls[k];\n+\t\t\t\tif (e.isDirectory()) {\n+\t\t\t\t\trecursiveDelete(e);\n+\t\t\t\t} else {\n+\t\t\t\t\te.delete();\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\t\tdir.delete();\n+\t\tif (dir.exists()) {\n+\t\t\tSystem.out.println(\"Warning: Failed to delete \" + dir);\n+\t\t}\n+\t}\n+\n+\tprotected void tearDown() throws Exception {\n+\t\twhile (!directoriesToDelete.isEmpty()) {\n+\t\t\tfinal File directory = directoriesToDelete.pop();\n+\t\t\trecursiveDelete(directory);\n+\t\t}\n+\t\tsuper.tearDown();\n+\t}\n+}\ndiff --git a/org.spearce.jgit.test/tst/org/spearce/jgit/lib/RepositoryTestCase.java b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/RepositoryTestCase.java\nindex aae9ed6..9719066 100644\n--- a/org.spearce.jgit.test/tst/org/spearce/jgit/lib/RepositoryTestCase.java\n+++ b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/RepositoryTestCase.java\n@@ -46,9 +46,7 @@ import java.io.InputStreamReader;\n import java.io.OutputStreamWriter;\n import java.io.Reader;\n \n-import junit.framework.TestCase;\n-\n-public abstract class RepositoryTestCase extends TestCase {\n+public abstract class RepositoryTestCase extends AbstractTestCase {\n \n \tprotected final File trashParent = new File(\"trash\");\n \n@@ -65,24 +63,6 @@ public abstract class RepositoryTestCase extends TestCase {\n \t\tjcommitter = new PersonIdent(\"J. Committer\", \"jcommitter@example.com\");\n \t}\n \n-\tprotected static void recursiveDelete(final File dir) {\n-\t\tfinal File[] ls = dir.listFiles();\n-\t\tif (ls != null) {\n-\t\t\tfor (int k = 0; k < ls.length; k++) {\n-\t\t\t\tfinal File e = ls[k];\n-\t\t\t\tif (e.isDirectory()) {\n-\t\t\t\t\trecursiveDelete(e);\n-\t\t\t\t} else {\n-\t\t\t\t\te.delete();\n-\t\t\t\t}\n-\t\t\t}\n-\t\t}\n-\t\tdir.delete();\n-\t\tif (dir.exists()) {\n-\t\t\tSystem.out.println(\"Warning: Failed to delete \" + dir);\n-\t\t}\n-\t}\n-\n \tprotected static void copyFile(final File src, final File dst)\n \t\t\tthrows IOException {\n \t\tfinal FileInputStream fis = new FileInputStream(src);\n-- \n1.5.4.3\n"},{"id":"79770","messageId":"1213382121-19786-24-git-send-email-florianskarten@web.de","threadId":"13934","inReplyTo":"4852BCCA.4030404@web.de","subject":"[JGIT PATCH v4 24/24] Added the test class AddCommandIterationTest.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-06-13T18:35:21Z","receivedAt":"2008-06-13T18:35:21Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Signed-off-by: Florian Koeberle <florianskarten@web.de>\n---\n .../treewalk/rules/AddCommandIterationTest.java    |  339 ++++++++++++++++++++\n 1 files changed, 339 insertions(+), 0 deletions(-)\n create mode 100644 org.spearce.jgit.test/tst/org/spearce/jgit/treewalk/rules/AddCommandIterationTest.java\n\ndiff --git a/org.spearce.jgit.test/tst/org/spearce/jgit/treewalk/rules/AddCommandIterationTest.java b/org.spearce.jgit.test/tst/org/spearce/jgit/treewalk/rules/AddCommandIterationTest.java\nnew file mode 100644\nindex 0000000..a17fc18\n--- /dev/null\n+++ b/org.spearce.jgit.test/tst/org/spearce/jgit/treewalk/rules/AddCommandIterationTest.java\n@@ -0,0 +1,339 @@\n+/*\n+ * Copyright (C) 2008, Florian KÃ¶berle <florianskarten@web.de>\n+ *\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or\n+ * without modification, are permitted provided that the following\n+ * conditions are met:\n+ *\n+ * - Redistributions of source code must retain the above copyright\n+ *   notice, this list of conditions and the following disclaimer.\n+ *\n+ * - Redistributions in binary form must reproduce the above\n+ *   copyright notice, this list of conditions and the following\n+ *   disclaimer in the documentation and/or other materials provided\n+ *   with the distribution.\n+ *\n+ * - Neither the name of the Git Development Community nor the\n+ *   names of its contributors may be used to endorse or promote\n+ *   products derived from this software without specific prior\n+ *   written permission.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n+ * CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+package org.spearce.jgit.treewalk.rules;\n+\n+import java.io.File;\n+import java.io.IOException;\n+import java.io.PrintWriter;\n+import java.util.ArrayList;\n+import java.util.Arrays;\n+import java.util.Collections;\n+import java.util.HashSet;\n+import java.util.Iterator;\n+import java.util.List;\n+import java.util.NoSuchElementException;\n+import java.util.Set;\n+\n+import org.spearce.jgit.errors.InvalidPatternException;\n+import org.spearce.jgit.errors.PathNotInProjectDirectoryException;\n+import org.spearce.jgit.lib.AbstractTestCase;\n+import org.spearce.jgit.lib.Repository;\n+import org.spearce.jgit.lib.WorkTree;\n+import org.spearce.jgit.treewalk.LightFileTreeIterable;\n+\n+public class AddCommandIterationTest extends AbstractTestCase {\n+\n+\tprivate WorkTree workTree;\n+\n+\tprivate AddRulesFactory factory;\n+\n+\tprivate Iterable<File> createIterable(File workingDirectory,\n+\t\t\tList<String> filePatternsOfAddCommand)\n+\t\t\tthrows PathNotInProjectDirectoryException, InvalidPatternException,\n+\t\t\tIOException {\n+\t\tfinal Rules rules = factory.createRules(workTree.getDirectory(),\n+\t\t\t\tworkingDirectory, filePatternsOfAddCommand);\n+\t\treturn new LightFileTreeIterable(workTree.getDirectory(), rules, false);\n+\t}\n+\n+\t@Override\n+\tprotected void setUp() throws Exception {\n+\t\tsuper.setUp();\n+\t\tfinal File projectDirectory = createTemporaryDirectory();\n+\t\tthis.workTree = Repository.createWorkTree(projectDirectory);\n+\t\tthis.factory = new AddRulesFactory();\n+\t}\n+\n+\tpublic void testNoPattern() throws Exception {\n+\t\tcreateFile(\"a.txt\");\n+\t\tfinal Iterable<File> iterable = createIterable(workTree.getDirectory(),\n+\t\t\t\tCollections.<String> emptyList());\n+\t\tfinal Set<File> expectedPaths = Collections.emptySet();\n+\t\tassertIsValidIterable(iterable);\n+\t\tassertIterableReturnsSet(expectedPaths, iterable);\n+\t}\n+\n+\tpublic void testTreePattern1() throws Exception {\n+\t\tfinal Set<File> expectedFiles = new HashSet<File>();\n+\t\tcreateFile(\"a.txt\");\n+\t\texpectedFiles.add(createFile(\"a\", \"a.txt\"));\n+\t\texpectedFiles.add(createFile(\"a\", \"a\", \"a.txt\"));\n+\t\texpectedFiles.add(createFile(\"a\", \"b\", \"a.txt\"));\n+\t\tcreateFile(\"a\", \"b\", \"a.c\");\n+\n+\t\tfinal File directoryA = new File(workTree.getDirectory(), \"a\");\n+\n+\t\tfinal Iterable<File> iterable = createIterable(directoryA, Arrays\n+\t\t\t\t.asList(\"*.txt\"));\n+\t\tassertIsValidIterable(iterable);\n+\t\tassertIterableReturnsSet(expectedFiles, iterable);\n+\t}\n+\n+\tpublic void testTreePattern2() throws Exception {\n+\t\tfinal Set<File> expectedFiles = new HashSet<File>();\n+\t\tcreateFile(\"a.txt\");\n+\t\texpectedFiles.add(createFile(\"a\", \"a.txt\"));\n+\t\texpectedFiles.add(createFile(\"a\", \"a\", \"a.txt\"));\n+\t\texpectedFiles.add(createFile(\"a\", \"b\", \"a.txt\"));\n+\t\tcreateFile(\"a\", \"b\", \"a.c\");\n+\n+\t\tfinal Iterable<File> iterable = createIterable(workTree.getDirectory(),\n+\t\t\t\tArrays.asList(\"a\" + File.separator + \"*.txt\"));\n+\t\tassertIsValidIterable(iterable);\n+\t\tassertIterableReturnsSet(expectedFiles, iterable);\n+\t}\n+\n+\tpublic void testSelectCompleteSubdirectory() throws Exception {\n+\t\tfinal Set<File> expectedPaths = new HashSet<File>();\n+\t\tfinal File directoryA = new File(workTree.getDirectory(), \"a\");\n+\t\tfinal File directoryAA = new File(directoryA, \"a\");\n+\t\tfinal File directoryAB = new File(directoryA, \"b\");\n+\t\tcreateFile(\"a.txt\");\n+\t\texpectedPaths.add(directoryA);\n+\t\texpectedPaths.add(directoryAA);\n+\t\texpectedPaths.add(createFile(\"a\", \"a.txt\"));\n+\t\texpectedPaths.add(createFile(\"a\", \"a\", \"a.txt\"));\n+\t\texpectedPaths.add(directoryAB);\n+\t\texpectedPaths.add(createFile(\"a\", \"b\", \"a.txt\"));\n+\t\texpectedPaths.add(createFile(\"a\", \"b\", \"a.c\"));\n+\n+\t\tfinal Iterable<File> iterable = createIterable(workTree.getDirectory(),\n+\t\t\t\tArrays.asList(\"a\"));\n+\n+\t\tassertIsValidIterable(iterable);\n+\t\tassertIterableReturnsSet(expectedPaths, iterable);\n+\t}\n+\n+\tpublic void testSelectTwoSubdirectories() throws Exception {\n+\t\tfinal Set<File> expectedPaths = new HashSet<File>();\n+\t\tfinal File directoryA = new File(workTree.getDirectory(), \"a\");\n+\t\tfinal File directoryAA = new File(directoryA, \"a\");\n+\t\tfinal File directoryAB = new File(directoryA, \"b\");\n+\t\tcreateFile(\"a.txt\");\n+\t\tcreateFile(\"a\", \"a.txt\");\n+\t\texpectedPaths.add(directoryAA);\n+\t\texpectedPaths.add(createFile(\"a\", \"a\", \"a.txt\"));\n+\t\texpectedPaths.add(directoryAB);\n+\t\texpectedPaths.add(createFile(\"a\", \"b\", \"a.txt\"));\n+\t\texpectedPaths.add(createFile(\"a\", \"b\", \"a.c\"));\n+\n+\t\tfinal List<String> patternList = new ArrayList<String>(2);\n+\t\tpatternList.add(\"a\" + File.separator + \"a\");\n+\t\tpatternList.add(\"a\" + File.separator + \"b\");\n+\t\tfinal Iterable<File> iterable = createIterable(workTree.getDirectory(),\n+\t\t\t\tpatternList);\n+\n+\t\tassertIsValidIterable(iterable);\n+\t\tassertIterableReturnsSet(expectedPaths, iterable);\n+\t}\n+\n+\tpublic void testTwoDifferentSelects() throws Exception {\n+\t\tfinal Set<File> expectedPaths = new HashSet<File>();\n+\t\tfinal File directoryA = new File(workTree.getDirectory(), \"a\");\n+\t\tfinal File directoryAA = new File(directoryA, \"a\");\n+\t\tcreateFile(\"a.txt\");\n+\t\tcreateFile(\"a\", \"a.txt\");\n+\t\texpectedPaths.add(directoryAA);\n+\t\texpectedPaths.add(createFile(\"a\", \"a\", \"a.txt\"));\n+\t\texpectedPaths.add(createFile(\"a\", \"b\", \"a.txt\"));\n+\t\texpectedPaths.add(createFile(\"a\", \"b\", \"c\", \"a.txt\"));\n+\t\tcreateFile(\"a\", \"b\", \"a.c\");\n+\n+\t\tfinal List<String> patternList = new ArrayList<String>(2);\n+\t\tpatternList.add(\"a\" + File.separator + \"a\");\n+\t\tpatternList.add(\"a\" + File.separator + \"b\" + File.separator + \"*.txt\");\n+\n+\t\tfinal Iterable<File> iterable = createIterable(workTree.getDirectory(),\n+\t\t\t\tpatternList);\n+\n+\t\tassertIsValidIterable(iterable);\n+\t\tassertIterableReturnsSet(expectedPaths, iterable);\n+\t}\n+\n+\tpublic void testRealisticExample() throws Exception {\n+\t\tfinal Set<File> expectedPaths = new HashSet<File>();\n+\n+\t\t// write the .gitignore file\n+\t\tfinal File dotGitIgnoreFile = createFile(\".gitignore\");\n+\t\tfinal PrintWriter dotGitIgnoreFilePrinter = new PrintWriter(\n+\t\t\t\tdotGitIgnoreFile);\n+\t\ttry {\n+\t\t\tdotGitIgnoreFilePrinter.println(\"/alpha/config.xml\");\n+\t\t\tdotGitIgnoreFilePrinter.println(\"*.class\");\n+\t\t\tdotGitIgnoreFilePrinter.println(\"!/alpha/test/ressources/\");\n+\t\t\tdotGitIgnoreFilePrinter.println(\"*~\");\n+\t\t} finally {\n+\t\t\tdotGitIgnoreFilePrinter.close();\n+\t\t}\n+\n+\t\t// write the .git/info/exclude file\n+\t\tfinal File repositoryDirectory = workTree.getRepository()\n+\t\t\t\t.getDirectory();\n+\t\tfinal File infoDirectory = new File(repositoryDirectory, \"info\");\n+\t\tinfoDirectory.mkdir();\n+\t\tfinal File infoExcludeFile = new File(infoDirectory, \"exclude\");\n+\t\tfinal PrintWriter infoExcludeFilePrinter = new PrintWriter(\n+\t\t\t\tinfoExcludeFile);\n+\t\ttry {\n+\t\t\tinfoExcludeFilePrinter.println(\"/alpha/test/ressources/mytest.txt\");\n+\t\t} finally {\n+\t\t\tinfoExcludeFilePrinter.close();\n+\t\t}\n+\n+\t\tcreateFile(\"alpha\", \"config.xml\");\n+\t\texpectedPaths.add(createFile(\"alpha\", \"src\", \"Main.java\"));\n+\t\tcreateFile(\"alpha\", \"src\", \"Main.class\");\n+\t\texpectedPaths.add(createFile(\"alpha\", \"test\", \"ressources\",\n+\t\t\t\t\"Example.class\"));\n+\t\texpectedPaths\n+\t\t\t\t.add(createFile(\"alpha\", \"test\", \"ressources\", \"input.txt\"));\n+\t\tcreateFile(\"alpha\", \"test\", \"ressources\", \"input.txt~\");\n+\t\tcreateFile(\"alpha\", \"test\", \"ressources\", \"mytest.txt\");\n+\n+\t\tfinal File alphaDirectory = new File(workTree.getDirectory(), \"alpha\");\n+\t\tfinal File srcDirectory = new File(alphaDirectory, \"src\");\n+\t\tfinal File testDirectory = new File(alphaDirectory, \"test\");\n+\t\tfinal File ressources = new File(testDirectory, \"ressources\");\n+\n+\t\texpectedPaths.add(alphaDirectory);\n+\t\texpectedPaths.add(srcDirectory);\n+\t\texpectedPaths.add(testDirectory);\n+\t\texpectedPaths.add(ressources);\n+\n+\t\tfinal List<String> patternList = new ArrayList<String>(2);\n+\t\tpatternList.add(\"alpha\");\n+\n+\t\tfinal Iterable<File> iterable = createIterable(workTree.getDirectory(),\n+\t\t\t\tpatternList);\n+\n+\t\tassertIsValidIterable(iterable);\n+\t\tassertIterableReturnsSet(expectedPaths, iterable);\n+\t}\n+\n+\tpublic void testSingleFile() throws Exception {\n+\t\tcreateFile(\"a.txt\");\n+\t\tcreateFile(\"a\", \"a.txt\");\n+\t\tcreateFile(\"a\", \"a\", \"a.txt\");\n+\t\tfinal File expectedFile = createFile(\"a\", \"b\", \"a.txt\");\n+\t\tcreateFile(\"a\", \"b\", \"a.c\");\n+\n+\t\tfinal String pattern = \"a\" + File.separator + \"b\" + File.separator\n+\t\t\t\t+ \"a.txt\";\n+\t\tfinal Iterable<File> iterable = createIterable(workTree.getDirectory(),\n+\t\t\t\tArrays.asList(pattern));\n+\t\tfinal Set<File> expectedPaths = Collections.singleton(expectedFile);\n+\t\tassertIsValidIterable(iterable);\n+\t\tassertIterableReturnsSet(expectedPaths, iterable);\n+\t}\n+\n+\t/**\n+\t * Tests if the specified {@link Iterable} returns the specified set of\n+\t * {@link File}s. The assertion will fail if the {@link Iterable} returns\n+\t * to much, to less files. It will also fail if the {@link Iterable} returns\n+\t * a file twice.\n+\t * \n+\t * @param expectedContent\n+\t *            the expected set of files.\n+\t * @param iterable\n+\t *            the {@link Iterable} to test.\n+\t */\n+\tprivate void assertIterableReturnsSet(Set<File> expectedContent,\n+\t\t\tIterable<File> iterable) {\n+\t\tfinal Set<File> returnedFiles = new HashSet<File>();\n+\t\tfinal List<File> doubleReturnedFiles = new ArrayList<File>();\n+\n+\t\tfinal Iterator<File> iterator = iterable.iterator();\n+\t\twhile (iterator.hasNext()) {\n+\t\t\tfinal File file = iterator.next();\n+\t\t\tif (!returnedFiles.add(file)) {\n+\t\t\t\tdoubleReturnedFiles.add(file);\n+\t\t\t}\n+\t\t}\n+\t\tfinal Set<File> missingFiles = new HashSet<File>();\n+\t\tfor (File file : expectedContent) {\n+\t\t\tif (!returnedFiles.contains(file)) {\n+\t\t\t\tmissingFiles.add(file);\n+\t\t\t}\n+\t\t}\n+\t\tif (!missingFiles.isEmpty()) {\n+\t\t\tfail(String.format(\"missing paths: %s\", missingFiles));\n+\t\t}\n+\n+\t\tfinal Set<File> unexpectedFiles = new HashSet<File>();\n+\t\tfor (File file : returnedFiles) {\n+\t\t\tif (!expectedContent.contains(file)) {\n+\t\t\t\tunexpectedFiles.add(file);\n+\t\t\t}\n+\t\t}\n+\t\tif (!unexpectedFiles.isEmpty()) {\n+\t\t\tfail(String.format(\"unexpected paths: %s\", unexpectedFiles));\n+\t\t}\n+\n+\t\tif (!doubleReturnedFiles.isEmpty()) {\n+\t\t\tfail(String.format(\"multiple times returned paths: %s\",\n+\t\t\t\t\tdoubleReturnedFiles));\n+\t\t}\n+\n+\t}\n+\n+\tprivate static void assertIsValidIterable(Iterable<File> iterable) {\n+\t\tfinal Iterator<File> iterator = iterable.iterator();\n+\t\twhile (iterator.hasNext()) {\n+\t\t\titerator.next();\n+\t\t}\n+\t\ttry {\n+\t\t\titerator.next();\n+\t\t\tfail();\n+\t\t} catch (NoSuchElementException e) {\n+\t\t\t// expected\n+\t\t}\n+\t}\n+\n+\tprivate File createFile(String... path) throws IOException {\n+\t\tFile file = workTree.getDirectory();\n+\t\tfor (int i = 0; i < path.length; i++) {\n+\t\t\tfile = new File(file, path[i]);\n+\t\t\tif (i == path.length - 1) {\n+\t\t\t\tfile.getParentFile().mkdirs();\n+\t\t\t\tfile.createNewFile();\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\t\treturn file;\n+\t}\n+}\n-- \n1.5.4.3\n"},{"id":"80205","messageId":"200806180843.43518.robin.rosenberg.lists@dewire.com","threadId":"13934","inReplyTo":"4852BCCA.4030404@web.de","subject":"Re: [JGIT PATCH v4] Implementation of fnmatch and the ignore rules","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg.lists@dewire.com","sentAt":"2008-06-18T06:43:43Z","receivedAt":"2008-06-18T06:43:43Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"fredagen den 13 juni 2008 20.30.34 skrev Florian Köberle:\n> Hi\n> \n> Thanks for the suggestions and comments, the new patches are available here:\n> http://repo.or.cz/w/egit/florian.git?a=shortlog;h=refs/heads/mailinglist-patches-4\n> \n> I will send them as a reply to this email soon.\n> \n> \n> The most noticeable change is that I improved the fnmatch functionality.\n> \n> All character classes of the type [:class:] work now.\n> Other character classes, including the character classes [=class=] and\n> [.class.] will cause a InvalidPatternException. The last two aren't\n> supported at my bash neighter, but are defined in the POSIX standard.\n> \n> Two other implementation differences are:\n> \n> The bash shell doesn't support the full range of digits, but my\n> implementatiton does. e.g. ۹ (U+06F9 EXTENDED ARABIC-INDIC DIGIT NINE)\n\nInteresting. I'm not sure what to say here. Full compatibility with Git or \"better\"?\n\n> A pattern like [[:] results in a InvalidPatternException in my\n> implementation. The shell has there a strange behavior: if the files \"[\"\n> and \":\" exists then \"ls [[:]\" shows only \":\".\n\nHaving : in  a filename is asking for trouble. I think the parser thinks [[: as \nin [[:alpha:]] and break the parsing somhow. This is possibly even undefined,\nso I think you should disallow this. [[\\:] works in bash btw.\n\n> The other main change is that I introduced a AbstractTestCase class\n> which which offers functionality to create temporary folders.\n> RepositoryTestCase extends now from this new class.\n> \n> An other patch reducing the duplication between AbstractTestCase and\n> RepositoryTestCase class will follow soon, if you like the change.\n\nNot trying to clean up got me into trouble with tons and tons of garbage, that\nis why I placed new repos in a directory and try to delete it if possible. That\nofcourse excludes parallell runs. Anyone with a good idea on how to\nreally handle this?\n\n> I also updated all license statements to the 3-clause BSD.\n> \n> Even if you don't like the last change (the AbstractTestCase change) it\n> would be cool if you would accept at least some patches.\n\nThe patch constituents are somwehat loose. Would this rebase do?\n\npick e331b13 Added the package fnmatch and two exceptions.\nsquash 64d8aa2 Added the interface FilePattern.\nsquash ae7915f Added the class Rule.\nsquash 48496f5 Added the interface Rules.\nsquash d7f58cb Added the class FileNamePattern.\nsquash f757bf1 Added the class FilePathPattern.\npick 39ea57e Added the class IgnoreRuleListFactory.\nsquash b61bf41 Added a Rules interface implementation and a factory for it.\npick f1c6c47 Added test class OverallIgnoreRulestest.\npick 5321c90 Formatted Constants class.\npick b59c160 Added constant REPOSITORY_DIRECTORY_NAME to Constants class.\nsquash 435b176 Added path related constants to the Constants class.\npick 76ad8d2 Added the class NoGitRepositoryFoundException.\npick 0164c9e Formatted Repository class.\npick fab1279 Added WorkTree class which can be constructed over Repository.\nsquash afda1f4 Added findWorkTree method to Repository class.\npick eb61f60 Formatted RepositoryTestCase.\npick 5aca2f0 Added a super class for RepositoryTestCase with a createTemporaryDirectory() method.\npick 9b6a188 Added the class LightFileTreeIterator and a test for it.\nsquash c9a4795 Added class LightFileTreeIterable.\npick 3b068aa Added the class PathNotInProjectDirectoryException.\npick ef7be7f Added the class AddRuleListFactory.\nsquash 0b81a9c Added class AddRulesFactory.\npick 9bbb0c3 Added the test class AddCommandIterationTest.\n\nThis groups patches into related chunks.\n\nI had to run native2ascii -encoding UTF-8 on FileNameMatcherTest.java to make it pass. The reason\nofcourse is that java doesn't specify a source file encoding. You can tell javac which encoding to use,\nbut I think we better avoid it. For author names in comments I think we have no choice but to state\nthat UTF-8 is the one and only encoding for comments and documentation where ascii is unavoidable.\n\nnative2ascii does these kinds of things\n\n        public void testWordroupCase1() throws Exception {\n-               assertMatch(\"[[:word:]]\", \"Ã¶\", true, false);\n+               assertMatch(\"[[:word:]]\", \"\\u00f6\", true, false);\n        }\n\n-- robin\n"}]}