git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* [JGIT PATCH v3 0/23] Implementation of a file tree iteration using ignore rules.
@ 2008-05-23 20:34 Florian Koeberle
  2008-05-23 20:34 ` [JGIT PATCH v3 01/23] Added the class InvalidPatternException Florian Koeberle
                   ` (25 more replies)
  0 siblings, 26 replies; 41+ messages in thread
From: Florian Koeberle @ 2008-05-23 20:34 UTC (permalink / raw)
  To: git


Hi

This patch set contains a new fnmatch implementation.

I dropped the idea of an regex based Matcher and implemented my own one.

The matcher matches character for character and can produce another matcher, which always starts at the position where it's parent was at creation time.

If you need to match:
very/long/path/a.txt
very/long/path/b.txt
very/long/path/c.txt

Then you can match "very/long/path" in matcher p and then "a.txt", "b.txt" and "c.txt" in another matcher c.

That works for any input pattern which are currently supported:
* characters
* the wildcards ? and *
* the wildcards ? and * with one character which should not appear like '/' 
* simple groups like [ab]
* ranges in groups like [a-c]
* inversed groups like [!ab]

Unsupported are colon expressions like ":alpha:". I didn't expect git-add to support it, but as I just noticed git does.
 
Also backslashes expressions like "\d" for digits are evaluated as the characters \ and d. Looks like git does the same for backslashes. In "git-add" patterns \  characters get replaced by / characters, as windows users might want to type a\b.txt instead of a/b.txt.

All implementations of FilePattern are now based on this matcher.
I combined as suggested the TreeFilePattern and the ComplexFilePattern into one class named FilePathPattern. I furthermore renamed the GlobalFilePattern into FileNamePattern.

"git add" patterns are now handled very similar to git, except that
a/\*/b.txt is also a valid pattern. It would match any path that starts with "a/" and ends with "/b.txt" independent of the number of slahes between.

 .../org/spearce/jgit/lib/FileNameMatcherTest.java  |  311 +++++++++++++
 .../jgit/treewalk/LightFileTreeIteratorTest.java   |  114 +++++
 .../treewalk/rules/AddCommandIterationTest.java    |  321 +++++++++++++
 .../treewalk/rules/OverallIgnoreRulesTest.java     |  375 +++++++++++++++
 .../jgit/errors/InvalidPatternException.java       |   44 ++
 .../jgit/errors/NoGitRepositoryFoundException.java |   28 ++
 .../errors/PathNotInProjectDirectoryException.java |   25 +
 .../src/org/spearce/jgit/lib/Constants.java        |   30 +-
 .../src/org/spearce/jgit/lib/FileNameMatcher.java  |  376 +++++++++++++++
 .../src/org/spearce/jgit/lib/Repository.java       |  482 +++++++++++++-------
 .../src/org/spearce/jgit/lib/WorkTree.java         |   67 +++
 .../jgit/treewalk/LightFileTreeIterable.java       |   59 +++
 .../jgit/treewalk/LightFileTreeIterator.java       |  112 +++++
 .../jgit/treewalk/rules/AddRuleListFactory.java    |   75 +++
 .../jgit/treewalk/rules/AddRulesFactory.java       |   90 ++++
 .../jgit/treewalk/rules/FileNamePattern.java       |   58 +++
 .../jgit/treewalk/rules/FilePathPattern.java       |   76 +++
 .../spearce/jgit/treewalk/rules/FilePattern.java   |  107 +++++
 .../jgit/treewalk/rules/IgnoreRuleListFactory.java |   94 ++++
 .../src/org/spearce/jgit/treewalk/rules/Rule.java  |   61 +++
 .../treewalk/rules/RuleListToObjectConverter.java  |  130 ++++++
 .../src/org/spearce/jgit/treewalk/rules/Rules.java |   99 ++++
 .../jgit/treewalk/rules/RulesImplementation.java   |   73 +++

Best regards,
Florian Koeberle

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [JGIT PATCH v3 01/23] Added the class InvalidPatternException.
  2008-05-23 20:34 [JGIT PATCH v3 0/23] Implementation of a file tree iteration using ignore rules Florian Koeberle
@ 2008-05-23 20:34 ` Florian Koeberle
  2008-05-23 20:34 ` [JGIT PATCH v3 02/23] Added the class FileNameMatcher and a test class for it Florian Koeberle
                   ` (24 subsequent siblings)
  25 siblings, 0 replies; 41+ messages in thread
From: Florian Koeberle @ 2008-05-23 20:34 UTC (permalink / raw)
  To: git; +Cc: Florian Koeberle

Signed-off-by: Florian Koeberle <florianskarten@web.de>
---
 .../jgit/errors/InvalidPatternException.java       |   44 ++++++++++++++++++++
 1 files changed, 44 insertions(+), 0 deletions(-)
 create mode 100644 org.spearce.jgit/src/org/spearce/jgit/errors/InvalidPatternException.java

diff --git a/org.spearce.jgit/src/org/spearce/jgit/errors/InvalidPatternException.java b/org.spearce.jgit/src/org/spearce/jgit/errors/InvalidPatternException.java
new file mode 100644
index 0000000..d09f0c9
--- /dev/null
+++ b/org.spearce.jgit/src/org/spearce/jgit/errors/InvalidPatternException.java
@@ -0,0 +1,44 @@
+/*
+ *  Copyright (C) 2008 Florian Köberle
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public
+ *  License, version 2, as published by the Free Software Foundation.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ */
+package org.spearce.jgit.errors;
+
+/**
+ * Thrown when a pattern passed in an argument was wrong.
+ * 
+ */
+public class InvalidPatternException extends Exception {
+	private final String pattern;
+
+	/**
+	 * @param message
+	 *            explains what was wrong with the pattern.
+	 * @param pattern
+	 *            the invalid pattern.
+	 */
+	public InvalidPatternException(String message, String pattern) {
+		super(message);
+		this.pattern = pattern;
+	}
+
+	/**
+	 * @return the invalid pattern.
+	 */
+	public String getPattern() {
+		return pattern;
+	}
+
+}
-- 
1.5.4.3

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [JGIT PATCH v3 02/23] Added the class FileNameMatcher and a test class for it.
  2008-05-23 20:34 [JGIT PATCH v3 0/23] Implementation of a file tree iteration using ignore rules Florian Koeberle
  2008-05-23 20:34 ` [JGIT PATCH v3 01/23] Added the class InvalidPatternException Florian Koeberle
@ 2008-05-23 20:34 ` Florian Koeberle
  2008-05-23 20:34 ` [JGIT PATCH v3 03/23] Added the interface FilePattern Florian Koeberle
                   ` (23 subsequent siblings)
  25 siblings, 0 replies; 41+ messages in thread
From: Florian Koeberle @ 2008-05-23 20:34 UTC (permalink / raw)
  To: git; +Cc: Florian Koeberle

Signed-off-by: Florian Koeberle <florianskarten@web.de>
---
 .../org/spearce/jgit/lib/FileNameMatcherTest.java  |  311 ++++++++++++++++
 .../src/org/spearce/jgit/lib/FileNameMatcher.java  |  376 ++++++++++++++++++++
 2 files changed, 687 insertions(+), 0 deletions(-)
 create mode 100644 org.spearce.jgit.test/tst/org/spearce/jgit/lib/FileNameMatcherTest.java
 create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/FileNameMatcher.java

diff --git a/org.spearce.jgit.test/tst/org/spearce/jgit/lib/FileNameMatcherTest.java b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/FileNameMatcherTest.java
new file mode 100644
index 0000000..fb0d8b2
--- /dev/null
+++ b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/FileNameMatcherTest.java
@@ -0,0 +1,311 @@
+package org.spearce.jgit.lib;
+
+import org.spearce.jgit.errors.InvalidPatternException;
+
+import junit.framework.TestCase;
+
+public class FileNameMatcherTest extends TestCase {
+
+	private void assertMatch(final String pattern, final String input,
+			final boolean matchExpected,
+			final boolean extendResultInNoMatchExpected)
+			throws InvalidPatternException {
+		final FileNameMatcher matcher = new FileNameMatcher(pattern, null);
+		matcher.extendStringToMatch(input);
+		assertEquals(matchExpected, matcher.isMatch());
+		assertEquals(extendResultInNoMatchExpected, matcher
+				.willExtendResultInNoMatch());
+	}
+
+	private void assertFileNameMatch(final String pattern, final String input,
+			final char excludedCharacter, final boolean matchExpected,
+			final boolean extendResultInNoMatchExpected)
+			throws InvalidPatternException {
+		final FileNameMatcher matcher = new FileNameMatcher(pattern,
+				new Character(excludedCharacter));
+		matcher.extendStringToMatch(input);
+		assertEquals(matchExpected, matcher.isMatch());
+		assertEquals(extendResultInNoMatchExpected, matcher
+				.willExtendResultInNoMatch());
+	}
+
+	public void testVerySimplePatternCase0() throws Exception {
+		assertMatch("", "", true, true);
+	}
+
+	public void testVerySimplePatternCase1() throws Exception {
+		assertMatch("ab", "a", false, false);
+	}
+
+	public void testVerySimplePatternCase2() throws Exception {
+		assertMatch("ab", "ab", true, true);
+	}
+
+	public void testVerySimplePatternCase3() throws Exception {
+		assertMatch("ab", "ac", false, true);
+	}
+
+	public void testVerySimplePatternCase4() throws Exception {
+		assertMatch("ab", "abc", false, true);
+	}
+
+	public void testVerySimpleWirdcardCase0() throws Exception {
+		assertMatch("?", "a", true, true);
+	}
+
+	public void testVerySimpleWildCardCase1() throws Exception {
+		assertMatch("??", "a", false, false);
+	}
+
+	public void testVerySimpleWildCardCase2() throws Exception {
+		assertMatch("??", "ab", true, true);
+	}
+
+	public void testVerySimpleWildCardCase3() throws Exception {
+		assertMatch("??", "abc", false, true);
+	}
+
+	public void testVerySimpleStarCase0() throws Exception {
+		assertMatch("*", "", true, false);
+	}
+
+	public void testVerySimpleStarCase1() throws Exception {
+		assertMatch("*", "a", true, false);
+	}
+
+	public void testVerySimpleStarCase2() throws Exception {
+		assertMatch("*", "ab", true, false);
+	}
+
+	public void testSimpleStarCase0() throws Exception {
+		assertMatch("a*b", "a", false, false);
+	}
+
+	public void testSimpleStarCase1() throws Exception {
+		assertMatch("a*c", "ac", true, false);
+	}
+
+	public void testSimpleStarCase2() throws Exception {
+		assertMatch("a*c", "ab", false, false);
+	}
+
+	public void testSimpleStarCase3() throws Exception {
+		assertMatch("a*c", "abc", true, false);
+	}
+
+	public void testManySolutionsCase0() throws Exception {
+		assertMatch("a*a*a", "aaa", true, false);
+	}
+
+	public void testManySolutionsCase1() throws Exception {
+		assertMatch("a*a*a", "aaaa", true, false);
+	}
+
+	public void testManySolutionsCase2() throws Exception {
+		assertMatch("a*a*a", "ababa", true, false);
+	}
+
+	public void testManySolutionsCase3() throws Exception {
+		assertMatch("a*a*a", "aaaaaaaa", true, false);
+	}
+
+	public void testManySolutionsCase4() throws Exception {
+		assertMatch("a*a*a", "aaaaaaab", false, false);
+	}
+
+	public void testVerySimpleGroupCase0() throws Exception {
+		assertMatch("[ab]", "a", true, true);
+	}
+
+	public void testVerySimpleGroupCase1() throws Exception {
+		assertMatch("[ab]", "b", true, true);
+	}
+
+	public void testVerySimpleGroupCase2() throws Exception {
+		assertMatch("[ab]", "ab", false, true);
+	}
+
+	public void testVerySimpleGroupRangeCase0() throws Exception {
+		assertMatch("[b-d]", "a", false, true);
+	}
+
+	public void testVerySimpleGroupRangeCase1() throws Exception {
+		assertMatch("[b-d]", "b", true, true);
+	}
+
+	public void testVerySimpleGroupRangeCase2() throws Exception {
+		assertMatch("[b-d]", "c", true, true);
+	}
+
+	public void testVerySimpleGroupRangeCase3() throws Exception {
+		assertMatch("[b-d]", "d", true, true);
+	}
+
+	public void testVerySimpleGroupRangeCase4() throws Exception {
+		assertMatch("[b-d]", "e", false, true);
+	}
+
+	public void testVerySimpleGroupRangeCase5() throws Exception {
+		assertMatch("[b-d]", "-", false, true);
+	}
+
+	public void testTwoGroupsCase0() throws Exception {
+		assertMatch("[b-d][ab]", "bb", true, true);
+	}
+
+	public void testTwoGroupsCase1() throws Exception {
+		assertMatch("[b-d][ab]", "ca", true, true);
+	}
+
+	public void testTwoGroupsCase2() throws Exception {
+		assertMatch("[b-d][ab]", "fa", false, true);
+	}
+
+	public void testTwoGroupsCase3() throws Exception {
+		assertMatch("[b-d][ab]", "bc", false, true);
+	}
+
+	public void testTwoRangesInOneGroupCase0() throws Exception {
+		assertMatch("[b-ce-e]", "a", false, true);
+	}
+
+	public void testTwoRangesInOneGroupCase1() throws Exception {
+		assertMatch("[b-ce-e]", "b", true, true);
+	}
+
+	public void testTwoRangesInOneGroupCase2() throws Exception {
+		assertMatch("[b-ce-e]", "c", true, true);
+	}
+
+	public void testTwoRangesInOneGroupCase3() throws Exception {
+		assertMatch("[b-ce-e]", "d", false, true);
+	}
+
+	public void testTwoRangesInOneGroupCase4() throws Exception {
+		assertMatch("[b-ce-e]", "e", true, true);
+	}
+
+	public void testTwoRangesInOneGroupCase5() throws Exception {
+		assertMatch("[b-ce-e]", "f", false, true);
+	}
+
+	public void testIncompleteRangesInOneGroupCase0() throws Exception {
+		assertMatch("a[b-]", "ab", true, true);
+	}
+
+	public void testIncompleteRangesInOneGroupCase1() throws Exception {
+		assertMatch("a[b-]", "ac", false, true);
+	}
+
+	public void testIncompleteRangesInOneGroupCase2() throws Exception {
+		assertMatch("a[b-]", "a-", true, true);
+	}
+
+	public void testCombinedRangesInOneGroupCase0() throws Exception {
+		assertMatch("[a-c-e]", "b", true, true);
+	}
+
+	/**
+	 * The c belongs to the range a-c. "-e" is no valid range so d should not
+	 * match.
+	 * 
+	 * @throws Exception
+	 *             for some reasons
+	 */
+	public void testCombinedRangesInOneGroupCase1() throws Exception {
+		assertMatch("[a-c-e]", "d", false, true);
+	}
+
+	public void testCombinedRangesInOneGroupCase2() throws Exception {
+		assertMatch("[a-c-e]", "e", true, true);
+	}
+
+	public void testInversedGroupCase0() throws Exception {
+		assertMatch("[!b-c]", "a", true, true);
+	}
+
+	public void testInversedGroupCase1() throws Exception {
+		assertMatch("[!b-c]", "b", false, true);
+	}
+
+	public void testInversedGroupCase2() throws Exception {
+		assertMatch("[!b-c]", "c", false, true);
+	}
+
+	public void testInversedGroupCase3() throws Exception {
+		assertMatch("[!b-c]", "d", true, true);
+	}
+
+	public void testFilePathSimpleCase() throws Exception {
+		assertFileNameMatch("a/b", "a/b", '/', true, true);
+	}
+
+	public void testFilePathCase0() throws Exception {
+		assertFileNameMatch("a*b", "a/b", '/', false, true);
+	}
+
+	public void testFilePathCase1() throws Exception {
+		assertFileNameMatch("a?b", "a/b", '/', false, true);
+	}
+
+	public void testFilePathCase2() throws Exception {
+		assertFileNameMatch("a*b", "a\\b", '\\', false, true);
+	}
+
+	public void testFilePathCase3() throws Exception {
+		assertFileNameMatch("a?b", "a\\b", '\\', false, true);
+	}
+
+	public void testReset() throws Exception {
+		final String pattern = "helloworld";
+		final FileNameMatcher matcher = new FileNameMatcher(pattern, null);
+		matcher.extendStringToMatch("helloworld");
+		assertEquals(true, matcher.isMatch());
+		assertEquals(true, matcher.willExtendResultInNoMatch());
+		matcher.resetStringToMatch();
+		matcher.extendStringToMatch("hello");
+		assertEquals(false, matcher.isMatch());
+		assertEquals(false, matcher.willExtendResultInNoMatch());
+		matcher.extendStringToMatch("world");
+		assertEquals(true, matcher.isMatch());
+		assertEquals(true, matcher.willExtendResultInNoMatch());
+		matcher.extendStringToMatch("to much");
+		assertEquals(false, matcher.isMatch());
+		assertEquals(true, matcher.willExtendResultInNoMatch());
+		matcher.resetStringToMatch();
+		matcher.extendStringToMatch("helloworld");
+		assertEquals(true, matcher.isMatch());
+		assertEquals(true, matcher.willExtendResultInNoMatch());
+	}
+
+	public void testCreateMatcherForSuffix() throws Exception {
+		final String pattern = "helloworld";
+		final FileNameMatcher matcher = new FileNameMatcher(pattern, null);
+		matcher.extendStringToMatch("hello");
+		final FileNameMatcher childMatcher = matcher.createMatcherForSuffix();
+		assertEquals(false, matcher.isMatch());
+		assertEquals(false, matcher.willExtendResultInNoMatch());
+		assertEquals(false, childMatcher.isMatch());
+		assertEquals(false, childMatcher.willExtendResultInNoMatch());
+		matcher.extendStringToMatch("world");
+		assertEquals(true, matcher.isMatch());
+		assertEquals(true, matcher.willExtendResultInNoMatch());
+		assertEquals(false, childMatcher.isMatch());
+		assertEquals(false, childMatcher.willExtendResultInNoMatch());
+		childMatcher.extendStringToMatch("world");
+		assertEquals(true, matcher.isMatch());
+		assertEquals(true, matcher.willExtendResultInNoMatch());
+		assertEquals(true, childMatcher.isMatch());
+		assertEquals(true, childMatcher.willExtendResultInNoMatch());
+		childMatcher.resetStringToMatch();
+		assertEquals(true, matcher.isMatch());
+		assertEquals(true, matcher.willExtendResultInNoMatch());
+		assertEquals(false, childMatcher.isMatch());
+		assertEquals(false, childMatcher.willExtendResultInNoMatch());
+		childMatcher.extendStringToMatch("world");
+		assertEquals(true, matcher.isMatch());
+		assertEquals(true, matcher.willExtendResultInNoMatch());
+		assertEquals(true, childMatcher.isMatch());
+		assertEquals(true, childMatcher.willExtendResultInNoMatch());
+	}
+}
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/FileNameMatcher.java b/org.spearce.jgit/src/org/spearce/jgit/lib/FileNameMatcher.java
new file mode 100644
index 0000000..4177e27
--- /dev/null
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/FileNameMatcher.java
@@ -0,0 +1,376 @@
+package org.spearce.jgit.lib;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.spearce.jgit.errors.InvalidPatternException;
+
+/**
+ * This class can be used to match filenames against fnmatch like patterns. It
+ * is not thread save.
+ */
+public class FileNameMatcher {
+	private static final List<Head> EMPTY_HEAD_LIST = Collections.emptyList();
+
+	private List<Head> headsStartValue;
+
+	private List<Head> heads;
+
+	/**
+	 * {{@link #extendStringToMatchByOneCharacter(char)} needs a list for the
+	 * new heads, allocating a new array would be bad for the performance, as
+	 * the method gets called very often.
+	 * 
+	 */
+	private List<Head> listForLocalUseage;
+
+	/**
+	 * 
+	 * @param headsStartValue
+	 *            must be a list which will never be modified.
+	 */
+	private FileNameMatcher(final List<Head> headsStartValue) {
+		this.headsStartValue = headsStartValue;
+		this.heads = new ArrayList<Head>(headsStartValue.size());
+		this.heads.addAll(this.headsStartValue);
+		this.listForLocalUseage = new ArrayList<Head>(headsStartValue.size());
+	}
+
+	/**
+	 * @param patternString
+	 *            must contain a pattern which fnmatch would accept.
+	 * @param invalidWildgetCharacter
+	 *            if this parameter isn't null then this character will not
+	 *            match at wildcards(* and ? are wildcards).
+	 * @throws InvalidPatternException
+	 *             if the patternString contains a invalid fnmatch pattern.
+	 */
+	public FileNameMatcher(final String patternString,
+			final Character invalidWildgetCharacter)
+			throws InvalidPatternException {
+		this(createHeadsStartValues(patternString, invalidWildgetCharacter));
+	}
+
+	private static List<Head> createHeadsStartValues(
+			final String patternString, final Character invalidWildgetCharacter)
+			throws InvalidPatternException {
+		List<Head> nextHeadsSuggestion = new ArrayList<Head>(2);
+		nextHeadsSuggestion.add(LastHead.INSTANCE);
+
+		final char previosChracter = '\n';
+		int i = patternString.length() - 1;
+		while (i >= 0) {
+			final char c = patternString.charAt(i);
+
+			switch (c) {
+			case '*': {
+				if (previosChracter != '*') {
+					final AbstractHead head = createWildCardHead(invalidWildgetCharacter);
+					nextHeadsSuggestion.add(head);
+					head.setNewHeads(nextHeadsSuggestion);
+				}
+				break;
+			}
+			case '?': {
+				final AbstractHead head = createWildCardHead(invalidWildgetCharacter);
+				head.setNewHeads(nextHeadsSuggestion);
+				nextHeadsSuggestion = new ArrayList<Head>(2);
+				nextHeadsSuggestion.add(head);
+				break;
+			}
+			case ']': {
+				final String groupPattern = extractGroupPatternWithoutBrackets(
+						patternString, i);
+				i -= groupPattern.length() + 1;
+				final AbstractHead head = new GroupHead(groupPattern);
+				head.setNewHeads(nextHeadsSuggestion);
+				nextHeadsSuggestion = new ArrayList<Head>(2);
+				nextHeadsSuggestion.add(head);
+				break;
+			}
+			case '[': {
+				final String message = String
+						.format("There is no closing ] for the character [ at "
+								+ i);
+				throw new InvalidPatternException(message, patternString);
+			}
+			default: {
+				final CharacterHead head = new CharacterHead(c);
+				head.setNewHeads(nextHeadsSuggestion);
+				nextHeadsSuggestion = new ArrayList<Head>(2);
+				nextHeadsSuggestion.add(head);
+			}
+			}
+			i--;
+
+		}
+		return nextHeadsSuggestion;
+	}
+
+	private static String extractGroupPatternWithoutBrackets(
+			final String patternString, int closingBracketIndex)
+			throws InvalidPatternException {
+		int start = closingBracketIndex - 1;
+		while (start >= 0) {
+			final char possibleStartCharacter = patternString.charAt(start);
+			if (possibleStartCharacter == '[') {
+				break;
+			}
+			if (possibleStartCharacter == ']') {
+				final String message = String
+						.format(
+								"Found two ] characters at %s and %s without a [ character between.",
+								String.valueOf(start), String
+										.valueOf(closingBracketIndex));
+				throw new InvalidPatternException(message, patternString);
+			}
+			start--;
+		}
+		if (start < 0) {
+			final String message = String
+					.format(
+							"Found a ] character at %s but no [ character infront of it.",
+							String.valueOf(closingBracketIndex));
+			throw new InvalidPatternException(message, patternString);
+		}
+		final String groupPatternWithOutBrackets = patternString.substring(
+				start + 1, closingBracketIndex);
+		return groupPatternWithOutBrackets;
+	}
+
+	private static AbstractHead createWildCardHead(
+			final Character invalidWildgetCharacter) {
+		if (invalidWildgetCharacter != null)
+			return new RestrictedWildCardHead(invalidWildgetCharacter
+					.charValue());
+		else
+			return new WildCardHead();
+	}
+
+	private void extendStringToMatchByOneCharacter(final char c) {
+		final List<Head> newHeads = listForLocalUseage;
+		newHeads.clear();
+		List<Head> lastAddedHeads = null;
+		for (int i = 0; i < heads.size(); i++) {
+			final Head head = heads.get(i);
+			final List<Head> headsToAdd = head.getNextHeads(c);
+			// Why the next performance optimization isn't wrong:
+			// Some times two heads return the very same list.
+			// We save future effort if we don't add these heads again.
+			// This is the case with the heads "a" and "*" of "a*b" which
+			// both can return the list ["*","b"]
+			if (headsToAdd != lastAddedHeads) {
+				newHeads.addAll(headsToAdd);
+				lastAddedHeads = headsToAdd;
+			}
+		}
+		listForLocalUseage = heads;
+		heads = newHeads;
+	}
+
+	/**
+	 * 
+	 * @param stringToMatch
+	 *            extends the string which is matched against the patterns of
+	 *            this class.
+	 */
+	public void extendStringToMatch(final String stringToMatch) {
+		for (int i = 0; i < stringToMatch.length(); i++) {
+			final char c = stringToMatch.charAt(i);
+			extendStringToMatchByOneCharacter(c);
+		}
+	}
+
+	/**
+	 * Resets this matcher to it's state right after construction.
+	 */
+	public void resetStringToMatch() {
+		heads.clear();
+		heads.addAll(headsStartValue);
+	}
+
+	/**
+	 * 
+	 * @return a {@link FileNameMatcher} instance which uses the same pattern
+	 *         like this matcher, but has the current state of this matcher as
+	 *         reset and start point.
+	 */
+	public FileNameMatcher createMatcherForSuffix() {
+		final List<Head> copyOfHeads = new ArrayList<Head>(heads.size());
+		copyOfHeads.addAll(heads);
+		return new FileNameMatcher(copyOfHeads);
+	}
+
+	private interface Head {
+		/**
+		 * 
+		 * @param c
+		 *            the character which decides which heads are returned.
+		 * @return a list of heads based on the input.
+		 */
+		public abstract List<Head> getNextHeads(char c);
+	}
+
+	private static abstract class AbstractHead implements Head {
+		private List<Head> newHeads = null;
+
+		protected abstract boolean matches(char c);
+
+		/**
+		 * 
+		 * @param newHeads
+		 *            a list of {@link Head}s which will not be modified.
+		 */
+		public final void setNewHeads(List<Head> newHeads) {
+			if (this.newHeads != null)
+				throw new IllegalStateException("Property is already non null");
+			this.newHeads = newHeads;
+		}
+
+		public List<Head> getNextHeads(char c) {
+			if (matches(c))
+				return newHeads;
+			else
+				return EMPTY_HEAD_LIST;
+		}
+	}
+
+	private static final class LastHead implements Head {
+		static final Head INSTANCE = new LastHead();
+
+		/**
+		 * Don't call this constructor, use {@link #INSTANCE}
+		 */
+		private LastHead() {
+			// defined because of javadoc and visibility modifier.
+		}
+
+		public List<Head> getNextHeads(char c) {
+			return EMPTY_HEAD_LIST;
+		}
+
+	}
+
+	private static final class CharacterHead extends AbstractHead {
+		private final char expectedCharacter;
+
+		protected CharacterHead(final char expectedCharacter) {
+			this.expectedCharacter = expectedCharacter;
+		}
+
+		@Override
+		protected final boolean matches(final char c) {
+			return c == expectedCharacter;
+		}
+
+	}
+
+	private static final class WildCardHead extends AbstractHead {
+		@Override
+		protected final boolean matches(final char c) {
+			return true;
+		}
+	}
+
+	private static final class RestrictedWildCardHead extends AbstractHead {
+		private final char excludedCharacter;
+
+		RestrictedWildCardHead(final char excludedCharacter) {
+			this.excludedCharacter = excludedCharacter;
+		}
+
+		@Override
+		protected final boolean matches(final char c) {
+			return c != excludedCharacter;
+		}
+	}
+
+	private static final class GroupHead extends AbstractHead {
+		private final List<CharacterRange> ranges;
+
+		private final boolean inverse;
+
+		GroupHead(String pattern) {
+			this.ranges = new ArrayList<CharacterRange>();
+			this.inverse = pattern.startsWith("!");
+			if (inverse) {
+				pattern = pattern.substring(1);
+			}
+			final Pattern regexPattern = Pattern.compile("[^-][-][^-]");
+			final Matcher matcher = regexPattern.matcher(pattern);
+			while (matcher.find()) {
+				final String rangeString = matcher.group(0);
+				final char start = rangeString.charAt(0);
+				final char end = rangeString.charAt(2);
+				ranges.add(new CharacterRange(start, end));
+				pattern = matcher.replaceFirst("");
+				matcher.reset(pattern);
+			}
+			// pattern contains now no ranges
+			for (int i = 0; i < pattern.length(); i++) {
+				final char c = pattern.charAt(i);
+				ranges.add(new CharacterRange(c, c));
+			}
+		}
+
+		@Override
+		protected final boolean matches(final char c) {
+			for (CharacterRange range : ranges) {
+				if (range.inRange(c)) {
+					return !inverse;
+				}
+			}
+			return inverse;
+		}
+
+		private static final class CharacterRange {
+			private final char start;
+
+			private final char end;
+
+			CharacterRange(char start, char end) {
+				this.start = start;
+				this.end = end;
+			}
+
+			boolean inRange(char c) {
+				return start <= c && c <= end;
+			}
+
+		}
+	}
+
+	/**
+	 * 
+	 * @return true, if the string currently beeing matched does match.
+	 */
+	public boolean isMatch() {
+		final ListIterator<Head> headIterator = heads
+				.listIterator(heads.size());
+		while (headIterator.hasPrevious()) {
+			final Head head = headIterator.previous();
+			if (head == LastHead.INSTANCE) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+	/**
+	 * 
+	 * @return true, if the string beeing matched will not match when the string
+	 *         gets extended.
+	 */
+	public boolean willExtendResultInNoMatch() {
+		for (int i = 0; i < heads.size(); i++) {
+			if (heads.get(i) != LastHead.INSTANCE) {
+				return false;
+			}
+		}
+		return true;
+	}
+}
-- 
1.5.4.3

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [JGIT PATCH v3 03/23] Added the interface FilePattern.
  2008-05-23 20:34 [JGIT PATCH v3 0/23] Implementation of a file tree iteration using ignore rules Florian Koeberle
  2008-05-23 20:34 ` [JGIT PATCH v3 01/23] Added the class InvalidPatternException Florian Koeberle
  2008-05-23 20:34 ` [JGIT PATCH v3 02/23] Added the class FileNameMatcher and a test class for it Florian Koeberle
@ 2008-05-23 20:34 ` Florian Koeberle
  2008-05-23 20:34 ` [JGIT PATCH v3 04/23] Added the class Rule Florian Koeberle
                   ` (22 subsequent siblings)
  25 siblings, 0 replies; 41+ messages in thread
From: Florian Koeberle @ 2008-05-23 20:34 UTC (permalink / raw)
  To: git; +Cc: Florian Koeberle

Signed-off-by: Florian Koeberle <florianskarten@web.de>
---
 .../spearce/jgit/treewalk/rules/FilePattern.java   |  107 ++++++++++++++++++++
 1 files changed, 107 insertions(+), 0 deletions(-)
 create mode 100644 org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/FilePattern.java

diff --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
new file mode 100644
index 0000000..75262c8
--- /dev/null
+++ b/org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/FilePattern.java
@@ -0,0 +1,107 @@
+/*
+ *  Copyright (C) 2008 Florian Köberle
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public
+ *  License, version 2, as published by the Free Software Foundation.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ */
+package org.spearce.jgit.treewalk.rules;
+
+/**
+ * A {@link FilePattern} can be used to check if files in a directory matches a
+ * pattern. It provides with the {@link #getPatternForSubDirectory(String)}
+ * method {@link FilePattern}s for sub directories.
+ * 
+ * Implementations of this interface should be immutable.
+ * 
+ */
+interface FilePattern {
+	/**
+	 * Contains the only instance of {@link FilePatternMatchAlways}.
+	 */
+	public static final FilePattern MATCH_ALWAYS = new FilePatternMatchAlways();
+
+	/**
+	 * Contains the only instance of {@link FilePatternMatchNever}.
+	 */
+	public static final FilePattern MATCH_NEVER = new FilePatternMatchNever();
+
+	/**
+	 * @param fileName
+	 *            the name of the file or directory
+	 * @param fileIsDirectory
+	 *            determines if the file is a directory.
+	 * @return true if the pattern matches.
+	 */
+	boolean match(String fileName, boolean fileIsDirectory);
+
+	/**
+	 * 
+	 * @param directoryName
+	 *            the name of a subdirectory.
+	 * @return a pattern which can be used to match files in sub directories. A
+	 *         user may check if the returned value is {@link #MATCH_NEVER} in
+	 *         order to do some performance optimizations.
+	 * 
+	 */
+	FilePattern getPatternForSubDirectory(String directoryName);
+
+	/**
+	 * @return true if {@link #getPatternForSubDirectory(String)} returns true
+	 *         for every value.
+	 */
+	boolean isSameForSubDirectories();
+
+	/**
+	 * This implementation does always match.
+	 */
+	public static final class FilePatternMatchAlways implements FilePattern {
+
+		private FilePatternMatchAlways() {
+			// declared to make the constructor private
+		}
+
+		public FilePattern getPatternForSubDirectory(String directoryName) {
+			return MATCH_ALWAYS;
+		}
+
+		public boolean match(String fileName, boolean fileIsDirectory) {
+			return true;
+		}
+
+		public boolean isSameForSubDirectories() {
+			return true;
+		}
+	}
+
+	/**
+	 * This implementation does never match.
+	 */
+	public static final class FilePatternMatchNever implements FilePattern {
+		private FilePatternMatchNever() {
+			// declared to make the constructor private
+		}
+
+		public FilePattern getPatternForSubDirectory(String directoryName) {
+			return MATCH_NEVER;
+		}
+
+		public boolean match(String fileName, boolean fileIsDirectory) {
+			return false;
+		}
+
+		public boolean isSameForSubDirectories() {
+			return true;
+		}
+	}
+
+}
-- 
1.5.4.3

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [JGIT PATCH v3 04/23] Added the class Rule.
  2008-05-23 20:34 [JGIT PATCH v3 0/23] Implementation of a file tree iteration using ignore rules Florian Koeberle
                   ` (2 preceding siblings ...)
  2008-05-23 20:34 ` [JGIT PATCH v3 03/23] Added the interface FilePattern Florian Koeberle
@ 2008-05-23 20:34 ` Florian Koeberle
  2008-05-23 20:34 ` [JGIT PATCH v3 05/23] Added the iterface Rules Florian Koeberle
                   ` (21 subsequent siblings)
  25 siblings, 0 replies; 41+ messages in thread
From: Florian Koeberle @ 2008-05-23 20:34 UTC (permalink / raw)
  To: git; +Cc: Florian Koeberle

Signed-off-by: Florian Koeberle <florianskarten@web.de>
---
 .../src/org/spearce/jgit/treewalk/rules/Rule.java  |   61 ++++++++++++++++++++
 1 files changed, 61 insertions(+), 0 deletions(-)
 create mode 100644 org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/Rule.java

diff --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
new file mode 100644
index 0000000..1cc74f5
--- /dev/null
+++ b/org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/Rule.java
@@ -0,0 +1,61 @@
+/*
+ *  Copyright (C) 2008 Florian Köberle
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public
+ *  License, version 2, as published by the Free Software Foundation.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ */
+package org.spearce.jgit.treewalk.rules;
+
+/**
+ * A Rule defines what to do with a files which match a specified
+ * {@link FilePattern}.
+ */
+public class Rule {
+	private boolean ignoreAtMatch;
+
+	private FilePattern pattern;
+
+	/**
+	 * 
+	 * @param ignoreAtMatch
+	 *            defines if the rules ignores or accepts at a match.
+	 * @param pattern
+	 *            the pattern used to test if a file matches.
+	 */
+	Rule(boolean ignoreAtMatch, FilePattern pattern) {
+		this.ignoreAtMatch = ignoreAtMatch;
+		this.pattern = pattern;
+	}
+
+	FilePattern getPattern() {
+		return pattern;
+	}
+
+	boolean isIgnoreAtMatch() {
+		return ignoreAtMatch;
+	}
+
+	Rule getRuleForSubDirectory(String directoryName) {
+		final FilePattern subPattern = pattern
+				.getPatternForSubDirectory(directoryName);
+		if (subPattern == pattern) {
+			return this;
+		}
+		return new Rule(ignoreAtMatch, subPattern);
+	}
+
+	boolean isSameForSubDirectories() {
+		return pattern.isSameForSubDirectories();
+	}
+
+}
-- 
1.5.4.3

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [JGIT PATCH v3 05/23] Added the iterface Rules.
  2008-05-23 20:34 [JGIT PATCH v3 0/23] Implementation of a file tree iteration using ignore rules Florian Koeberle
                   ` (3 preceding siblings ...)
  2008-05-23 20:34 ` [JGIT PATCH v3 04/23] Added the class Rule Florian Koeberle
@ 2008-05-23 20:34 ` Florian Koeberle
  2008-06-06  0:22   ` Robin Rosenberg
  2008-05-23 20:34 ` [JGIT PATCH v3 06/23] Added the class FileNamePattern Florian Koeberle
                   ` (20 subsequent siblings)
  25 siblings, 1 reply; 41+ messages in thread
From: Florian Koeberle @ 2008-05-23 20:34 UTC (permalink / raw)
  To: git; +Cc: Florian Koeberle

Signed-off-by: Florian Koeberle <florianskarten@web.de>
---
 .../src/org/spearce/jgit/treewalk/rules/Rules.java |   99 ++++++++++++++++++++
 1 files changed, 99 insertions(+), 0 deletions(-)
 create mode 100644 org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/Rules.java

diff --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
new file mode 100644
index 0000000..627d974
--- /dev/null
+++ b/org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/Rules.java
@@ -0,0 +1,99 @@
+/*
+ *  Copyright (C) 2008 Florian Köberle
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public
+ *  License, version 2, as published by the Free Software Foundation.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ */
+package org.spearce.jgit.treewalk.rules;
+
+/**
+ * A {@link Rules} instances defines ignore or do not ignore rules for files in
+ * a directory. It can't directly be used to match files in sub directories, but
+ * provides a method {@link #getRulesForSubDirectory}.
+ * 
+ */
+public interface Rules {
+
+	/**
+	 * Provides the instance of {@link IgnoreAllRules}.
+	 */
+	public static final Rules IGNORE_ALL = new IgnoreAllRules();
+
+	/**
+	 * Provides the instance of {@link IgnoreNothingRules}.
+	 */
+	public static final Rules IGNORE_NOTHING = new IgnoreNothingRules();
+
+	/**
+	 * @param fileName
+	 *            the name of the file or directory.
+	 * @param fileIsDirectory
+	 *            should be true if the file is a directory.
+	 * @return true if the file or directory should be ignored.
+	 */
+	public abstract boolean toIgnore(String fileName, boolean fileIsDirectory);
+
+	/**
+	 * @param directoryName
+	 *            the sub directory for which you want an {@link Rules}
+	 *            instance.
+	 * @return an {@link Rules} instance, which can be used to check files in
+	 *         the specified sub directory.
+	 */
+	public abstract Rules getRulesForSubDirectory(String directoryName);
+
+	/**
+	 * This implementation ignores everything.
+	 */
+	public static final class IgnoreAllRules implements Rules {
+		private IgnoreAllRules() {
+			// declared to make the constructor private
+		}
+
+		public Rules getRulesForSubDirectory(String directoryName) {
+			return this;
+		}
+
+		public boolean toIgnore(String fileName, boolean fileIsDirectory) {
+			return true;
+		}
+
+		@Override
+		public String toString() {
+			return "ignore all rules";
+		}
+	}
+
+	/**
+	 * This implementation ignores nothing.
+	 */
+	public static final class IgnoreNothingRules implements Rules {
+		private IgnoreNothingRules() {
+			// declared to make the constructor private
+		}
+
+		public Rules getRulesForSubDirectory(String directoryName) {
+			return this;
+		}
+
+		public boolean toIgnore(String fileName, boolean fileIsDirectory) {
+			return false;
+		}
+
+		@Override
+		public String toString() {
+			return "ignore nothing rules";
+		}
+	}
+
+}
-- 
1.5.4.3

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [JGIT PATCH v3 06/23] Added the class FileNamePattern.
  2008-05-23 20:34 [JGIT PATCH v3 0/23] Implementation of a file tree iteration using ignore rules Florian Koeberle
                   ` (4 preceding siblings ...)
  2008-05-23 20:34 ` [JGIT PATCH v3 05/23] Added the iterface Rules Florian Koeberle
@ 2008-05-23 20:34 ` Florian Koeberle
  2008-06-06  0:22   ` Robin Rosenberg
  2008-05-23 20:34 ` [JGIT PATCH v3 07/23] Added the class FilePathPattern Florian Koeberle
                   ` (19 subsequent siblings)
  25 siblings, 1 reply; 41+ messages in thread
From: Florian Koeberle @ 2008-05-23 20:34 UTC (permalink / raw)
  To: git; +Cc: Florian Koeberle

Signed-off-by: Florian Koeberle <florianskarten@web.de>
---
 .../jgit/treewalk/rules/FileNamePattern.java       |   58 ++++++++++++++++++++
 1 files changed, 58 insertions(+), 0 deletions(-)
 create mode 100644 org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/FileNamePattern.java

diff --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
new file mode 100644
index 0000000..f14fdef
--- /dev/null
+++ b/org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/FileNamePattern.java
@@ -0,0 +1,58 @@
+/*
+ *  Copyright (C) 2008 Florian Köberle
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public
+ *  License, version 2, as published by the Free Software Foundation.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ */
+package org.spearce.jgit.treewalk.rules;
+
+import org.spearce.jgit.errors.InvalidPatternException;
+import org.spearce.jgit.lib.FileNameMatcher;
+
+/**
+ * A {@link FileNamePattern} defines a pattern for all files in a tree. A
+ * typical example would be "*.txt", which would match at any file or subtree
+ * which ends with ".txt" like "a/b/c.txt" and "a.txt/a.c".
+ * 
+ */
+class FileNamePattern implements FilePattern {
+	private final FileNameMatcher fileNameMatcher;
+
+	private final boolean matchDirectoriesOnly;
+
+	FileNamePattern(String fnMatchPatternString, boolean matchDirectoriesOnly)
+			throws InvalidPatternException {
+		this.fileNameMatcher = new FileNameMatcher(fnMatchPatternString, null);
+		this.matchDirectoriesOnly = matchDirectoriesOnly;
+	}
+
+	public FilePattern getPatternForSubDirectory(String directoryName) {
+		if (match(directoryName, true)) {
+			return MATCH_ALWAYS;
+		}
+		return this;
+	}
+
+	public boolean match(String fileName, boolean fileIsDirectory) {
+		if (matchDirectoriesOnly && !fileIsDirectory) {
+			return false;
+		}
+		fileNameMatcher.resetStringToMatch();
+		fileNameMatcher.extendStringToMatch(fileName);
+		return fileNameMatcher.isMatch();
+	}
+
+	public boolean isSameForSubDirectories() {
+		return false;
+	}
+}
-- 
1.5.4.3

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [JGIT PATCH v3 07/23] Added the class FilePathPattern.
  2008-05-23 20:34 [JGIT PATCH v3 0/23] Implementation of a file tree iteration using ignore rules Florian Koeberle
                   ` (5 preceding siblings ...)
  2008-05-23 20:34 ` [JGIT PATCH v3 06/23] Added the class FileNamePattern Florian Koeberle
@ 2008-05-23 20:34 ` Florian Koeberle
  2008-05-23 20:34 ` [JGIT PATCH v3 08/23] Added the class IgnoreRuleListFactory Florian Koeberle
                   ` (18 subsequent siblings)
  25 siblings, 0 replies; 41+ messages in thread
From: Florian Koeberle @ 2008-05-23 20:34 UTC (permalink / raw)
  To: git; +Cc: Florian Koeberle

Signed-off-by: Florian Koeberle <florianskarten@web.de>
---
 .../jgit/treewalk/rules/FilePathPattern.java       |   76 ++++++++++++++++++++
 1 files changed, 76 insertions(+), 0 deletions(-)
 create mode 100644 org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/FilePathPattern.java

diff --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
new file mode 100644
index 0000000..4a5f021
--- /dev/null
+++ b/org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/FilePathPattern.java
@@ -0,0 +1,76 @@
+/*
+ *  Copyright (C) 2008 Florian Köberle
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public
+ *  License, version 2, as published by the Free Software Foundation.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ */
+package org.spearce.jgit.treewalk.rules;
+
+import org.spearce.jgit.errors.InvalidPatternException;
+import org.spearce.jgit.lib.FileNameMatcher;
+
+/**
+ * A {@link FilePathPattern} represents a pattern for a file path.
+ * 
+ */
+class FilePathPattern implements FilePattern {
+	private final FileNameMatcher matcher;
+
+	private final boolean matchDirectoriesOnly;
+
+	private FilePathPattern(final FileNameMatcher matcher,
+			final boolean matchDirectoriesOnly) {
+		this.matcher = matcher;
+		this.matchDirectoriesOnly = matchDirectoriesOnly;
+	}
+
+	FilePathPattern(final String pattern, final boolean allowSlashInWildCard,
+			final boolean matchDirectoriesOnly) throws InvalidPatternException {
+
+		if (allowSlashInWildCard)
+			this.matcher = new FileNameMatcher(pattern, null);
+		else
+			this.matcher = new FileNameMatcher(pattern, new Character('/'));
+		this.matchDirectoriesOnly = matchDirectoriesOnly;
+	}
+
+	public FilePattern getPatternForSubDirectory(String directoryName) {
+		matcher.resetStringToMatch();
+		matcher.extendStringToMatch(directoryName);
+
+		if (matcher.isMatch())
+			return FilePattern.MATCH_ALWAYS;
+
+		matcher.extendStringToMatch("/");
+
+		if (matcher.willExtendResultInNoMatch())
+			return FilePattern.MATCH_NEVER;
+
+		final FileNameMatcher childMatcher = matcher.createMatcherForSuffix();
+		return new FilePathPattern(childMatcher, matchDirectoriesOnly);
+	}
+
+	public boolean match(String fileName, boolean fileIsDirectory) {
+		if (!fileIsDirectory && matchDirectoriesOnly) {
+			return false;
+		}
+		matcher.resetStringToMatch();
+		matcher.extendStringToMatch(fileName);
+		return matcher.isMatch();
+	}
+
+	public boolean isSameForSubDirectories() {
+		return false;
+	}
+
+}
-- 
1.5.4.3

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [JGIT PATCH v3 08/23] Added the class IgnoreRuleListFactory.
  2008-05-23 20:34 [JGIT PATCH v3 0/23] Implementation of a file tree iteration using ignore rules Florian Koeberle
                   ` (6 preceding siblings ...)
  2008-05-23 20:34 ` [JGIT PATCH v3 07/23] Added the class FilePathPattern Florian Koeberle
@ 2008-05-23 20:34 ` Florian Koeberle
  2008-05-23 20:34 ` [JGIT PATCH v3 09/23] Added a Rules interface implementation and a factory for it Florian Koeberle
                   ` (17 subsequent siblings)
  25 siblings, 0 replies; 41+ messages in thread
From: Florian Koeberle @ 2008-05-23 20:34 UTC (permalink / raw)
  To: git; +Cc: Florian Koeberle

Signed-off-by: Florian Koeberle <florianskarten@web.de>
---
 .../jgit/treewalk/rules/IgnoreRuleListFactory.java |   94 ++++++++++++++++++++
 1 files changed, 94 insertions(+), 0 deletions(-)
 create mode 100644 org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/IgnoreRuleListFactory.java

diff --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
new file mode 100644
index 0000000..98f1169
--- /dev/null
+++ b/org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/IgnoreRuleListFactory.java
@@ -0,0 +1,94 @@
+/*
+ *  Copyright (C) 2008 Florian Köberle
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public
+ *  License, version 2, as published by the Free Software Foundation.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ */
+package org.spearce.jgit.treewalk.rules;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Scanner;
+
+import org.spearce.jgit.errors.InvalidPatternException;
+
+/**
+ * This class can be used to create lists of {@link Rule} objects from lines of
+ * .gitignore like files.
+ * 
+ */
+class IgnoreRuleListFactory {
+
+	List<Rule> createIgnoreRuleList(final Iterable<String> lineIterable)
+			throws InvalidPatternException {
+		LinkedList<Rule> rules = new LinkedList<Rule>();
+		for (String line : lineIterable) {
+			final String trimmedLine = line.trim();
+			if (trimmedLine.startsWith("#")) {
+				continue;
+			}
+			if (trimmedLine.length() == 0) {
+				continue;
+			}
+			rules.add(0, createRule(trimmedLine));
+		}
+		return rules;
+	}
+
+	List<Rule> createIgnoreRuleList(final List<File> files)
+			throws FileNotFoundException, InvalidPatternException {
+		final List<String> lines = new ArrayList<String>();
+		for (File file : files) {
+			Scanner scanner = new Scanner(file);
+			try {
+				while (scanner.hasNextLine()) {
+					lines.add(scanner.nextLine());
+				}
+			} finally {
+				scanner.close();
+			}
+		}
+		return createIgnoreRuleList(lines);
+	}
+
+	private Rule createRule(String patternString)
+			throws InvalidPatternException {
+		final boolean inverse = patternString.startsWith("!");
+		if (inverse)
+			patternString = patternString.substring(1);
+
+		final FilePattern pattern = createFilePattern(patternString);
+		return new Rule(!inverse, pattern);
+	}
+
+	private FilePattern createFilePattern(String patternString)
+			throws InvalidPatternException {
+		final boolean matchDirectoriesOnly = patternString.endsWith("/");
+		if (matchDirectoriesOnly)
+			patternString = patternString.substring(0,
+					patternString.length() - 1);
+		if (patternString.contains("/")) {
+			if (patternString.startsWith("/"))
+				patternString = patternString.substring(1);
+
+			return new FilePathPattern(patternString, false,
+					matchDirectoriesOnly);
+		} else {
+			return new FileNamePattern(patternString, matchDirectoriesOnly);
+		}
+	}
+
+}
-- 
1.5.4.3

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [JGIT PATCH v3 09/23] Added a Rules interface implementation and a factory for it.
  2008-05-23 20:34 [JGIT PATCH v3 0/23] Implementation of a file tree iteration using ignore rules Florian Koeberle
                   ` (7 preceding siblings ...)
  2008-05-23 20:34 ` [JGIT PATCH v3 08/23] Added the class IgnoreRuleListFactory Florian Koeberle
@ 2008-05-23 20:34 ` Florian Koeberle
  2008-06-06  0:23   ` Robin Rosenberg
  2008-05-23 20:34 ` [JGIT PATCH v3 10/23] Added test class OverallIgnoreRulestest Florian Koeberle
                   ` (16 subsequent siblings)
  25 siblings, 1 reply; 41+ messages in thread
From: Florian Koeberle @ 2008-05-23 20:34 UTC (permalink / raw)
  To: git; +Cc: Florian Koeberle

Signed-off-by: Florian Koeberle <florianskarten@web.de>
---
 .../treewalk/rules/RuleListToObjectConverter.java  |  130 ++++++++++++++++++++
 .../jgit/treewalk/rules/RulesImplementation.java   |   73 +++++++++++
 2 files changed, 203 insertions(+), 0 deletions(-)
 create mode 100644 org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/RuleListToObjectConverter.java
 create mode 100644 org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/RulesImplementation.java

diff --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
new file mode 100644
index 0000000..b67beff
--- /dev/null
+++ b/org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/RuleListToObjectConverter.java
@@ -0,0 +1,130 @@
+/*
+ *  Copyright (C) 2008 Florian Köberle
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public
+ *  License, version 2, as published by the Free Software Foundation.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ */
+package org.spearce.jgit.treewalk.rules;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * This class converts a list of {@link Rule} objects into a {@Rules} object.
+ * During the conversion some optimizations are done:
+ * <ul>
+ * <li>Rules which can never match are removed. e.g. There is no need to check
+ * the rule "/a" in the directory b.</li>
+ * <li>The list is cut at the first rule which match always. *.txt\n/a for
+ * example would result in an internal list "ignore all, ignore *.txt" which is
+ * then reduced to "ignore all".</li>
+ * <li>Ignore rules which are direcly before an "ignore all" all rule are
+ * removed. /a\n*.txt for example would result in an intern "ignore *.txt,
+ * ignore all" list which is then reduced to "ignore all",</li>
+ * <li>"do not ignore" rules at the bottom of the intern list are removed. This
+ * optimization would remove !a from "!a\n/b" as it is in the inversed list at
+ * the bottom.</li>
+ * </ul>
+ */
+class RuleListToObjectConverter {
+	protected Rules createIgnoreRules(Iterator<Rule> ruleIterator) {
+		final List<Rule> rules = getNessesaryRulesFromIterator(ruleIterator);
+		removeUnnecessaryDoNotIgnoreRulesAtTheEndOfTheList(rules);
+		removeUnnecessaryIgnoreRulesNearTheEndOfTheList(rules);
+
+		if (rules.size() == 1) {
+			final Rule rule = rules.get(0);
+			if (rule.getPattern() == FilePattern.MATCH_ALWAYS) {
+				if (rule.isIgnoreAtMatch()) {
+					return Rules.IGNORE_ALL;
+				} else {
+					return Rules.IGNORE_NOTHING;
+				}
+			}
+		} else if (rules.isEmpty()) {
+			return Rules.IGNORE_NOTHING;
+		}
+		return new RulesImplementation(rules, this);
+	}
+
+	private List<Rule> getNessesaryRulesFromIterator(Iterator<Rule> ruleIterator) {
+		final List<Rule> rules = new ArrayList<Rule>();
+		while (ruleIterator.hasNext()) {
+			final Rule subRule = ruleIterator.next();
+			if (subRule.getPattern() == FilePattern.MATCH_NEVER) {
+				continue;
+			}
+			rules.add(subRule);
+			// There is no need for rules after a rule witch match always,
+			// as such a rule would never be the first rule which matches.
+			if (subRule.getPattern() == FilePattern.MATCH_ALWAYS) {
+				break;
+			}
+		}
+		return rules;
+	}
+
+	/**
+	 * Expects that
+	 * {@link #removeUnnecessaryDoNotIgnoreRulesAtTheEndOfTheList(List)} has
+	 * been executed first.
+	 * 
+	 * @param rules
+	 *            rule list to reduce.
+	 */
+	private void removeUnnecessaryIgnoreRulesNearTheEndOfTheList(
+			final List<Rule> rules) {
+		// Why the following optimization makes only sense for the end of the
+		// list:
+		// If there is a "ignore all"- rule,
+		// then it is located at the end of the list
+		// See how the list is filled to prove this statement.
+		if (rules.size() >= 2) {
+			final Rule lastRule = rules.get(rules.size() - 1);
+			assert lastRule.isIgnoreAtMatch() : "Expected that no 'not ignore'-rule is at the end of the list any more";
+			final boolean ignoreAllAtEnd = lastRule.getPattern().equals(
+					FilePattern.MATCH_ALWAYS);
+			if (ignoreAllAtEnd) {
+				while (rules.size() >= 2) {
+					final int ruleBeforeLastIndex = rules.size() - 2;
+					final Rule ruleBeforeLast = rules.get(ruleBeforeLastIndex);
+					if (ruleBeforeLast.isIgnoreAtMatch()) {
+						rules.remove(ruleBeforeLastIndex);
+					} else {
+						break;
+					}
+				}
+			}
+		}
+	}
+
+	private void removeUnnecessaryDoNotIgnoreRulesAtTheEndOfTheList(
+			final List<Rule> rules) {
+		// Why it is save to remove "don't ignore rules" at the end of the list
+		// if there is no "ignore rule" below a "don't ignore rule" then
+		// the path which haven't match jet will never be ignored:
+		// -> if another "don't ignore rule" match then the patch will not be
+		// ignored
+		// -> if no "don't ignore rule" match then the path will not be ignored.
+		while (!rules.isEmpty()) {
+			final int indexOfLastRule = rules.size() - 1;
+			final Rule lastRule = rules.get(indexOfLastRule);
+			if (lastRule.isIgnoreAtMatch()) {
+				break;
+			} else {
+				rules.remove(indexOfLastRule);
+			}
+		}
+	}
+}
diff --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
new file mode 100644
index 0000000..458b327
--- /dev/null
+++ b/org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/RulesImplementation.java
@@ -0,0 +1,73 @@
+/*
+ *  Copyright (C) 2008 Florian Köberle
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public
+ *  License, version 2, as published by the Free Software Foundation.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ */
+package org.spearce.jgit.treewalk.rules;
+
+import java.util.Iterator;
+import java.util.List;
+
+class RulesImplementation implements Rules {
+	/**
+	 * Complete list of rules. Note that order is: determining rule first.
+	 */
+	private final List<Rule> rules;
+
+	/**
+	 * Factory used to create {@link Rules} for sub directories.
+	 */
+	private RuleListToObjectConverter factory;
+
+	RulesImplementation(List<Rule> rules, RuleListToObjectConverter factory) {
+		this.rules = rules;
+		this.factory = factory;
+	}
+
+	/**
+	 * @see Rules#toIgnore(java.lang.String, boolean)
+	 */
+	public boolean toIgnore(String fileName, boolean fileIsDirectory) {
+		for (Rule rule : rules) {
+			if (rule.getPattern().match(fileName, fileIsDirectory)) {
+				return rule.isIgnoreAtMatch();
+			}
+		}
+		return false;
+	}
+
+	/**
+	 * @see Rules#getRulesForSubDirectory(java.lang.String)
+	 */
+	public Rules getRulesForSubDirectory(final String directoryName) {
+		final Iterator<Rule> subRuleIterator = new Iterator<Rule>() {
+			final Iterator<Rule> ruleIterator = rules.iterator();
+
+			public boolean hasNext() {
+				return ruleIterator.hasNext();
+			}
+
+			public Rule next() {
+				return ruleIterator.next()
+						.getRuleForSubDirectory(directoryName);
+			}
+
+			public void remove() {
+				throw new UnsupportedOperationException();
+			}
+
+		};
+		return factory.createIgnoreRules(subRuleIterator);
+	}
+}
-- 
1.5.4.3

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [JGIT PATCH v3 10/23] Added test class OverallIgnoreRulestest.
  2008-05-23 20:34 [JGIT PATCH v3 0/23] Implementation of a file tree iteration using ignore rules Florian Koeberle
                   ` (8 preceding siblings ...)
  2008-05-23 20:34 ` [JGIT PATCH v3 09/23] Added a Rules interface implementation and a factory for it Florian Koeberle
@ 2008-05-23 20:34 ` Florian Koeberle
  2008-05-23 20:34 ` [JGIT PATCH v3 11/23] Added the class PathNotInProjectDirectoryException Florian Koeberle
                   ` (15 subsequent siblings)
  25 siblings, 0 replies; 41+ messages in thread
From: Florian Koeberle @ 2008-05-23 20:34 UTC (permalink / raw)
  To: git; +Cc: Florian Koeberle

Signed-off-by: Florian Koeberle <florianskarten@web.de>
---
 .../treewalk/rules/OverallIgnoreRulesTest.java     |  375 ++++++++++++++++++++
 1 files changed, 375 insertions(+), 0 deletions(-)
 create mode 100644 org.spearce.jgit.test/tst/org/spearce/jgit/treewalk/rules/OverallIgnoreRulesTest.java

diff --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
new file mode 100644
index 0000000..71718bf
--- /dev/null
+++ b/org.spearce.jgit.test/tst/org/spearce/jgit/treewalk/rules/OverallIgnoreRulesTest.java
@@ -0,0 +1,375 @@
+/*
+ *  Copyright (C) 2008 Florian Köberle
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public
+ *  License, version 2, as published by the Free Software Foundation.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ */
+package org.spearce.jgit.treewalk.rules;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.spearce.jgit.errors.InvalidPatternException;
+
+import junit.framework.TestCase;
+
+public class OverallIgnoreRulesTest extends TestCase {
+	private IgnoreRulesFactory factory;
+
+	@Override
+	protected void setUp() throws Exception {
+		factory = new IgnoreRulesFactory();
+	}
+
+	public void testSimpleGlobalPattern() throws Exception {
+		List<String> lines = new ArrayList<String>();
+		lines.add("ab");
+		final Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);
+		assertTrue(ignoreRules.toIgnore("ab", false));
+		assertTrue(ignoreRules.toIgnore("ab", true));
+		assertFalse(ignoreRules.toIgnore("abc", false));
+		assertFalse(ignoreRules.toIgnore("abc", true));
+	}
+
+	public void testGlobalPatternWithOneStar() throws Exception {
+		List<String> lines = new ArrayList<String>();
+		lines.add("a*c");
+		final Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);
+
+		assertTrue(ignoreRules.toIgnore("ac", false));
+		assertTrue(ignoreRules.toIgnore("ac", true));
+
+		assertTrue(ignoreRules.toIgnore("abc", false));
+		assertTrue(ignoreRules.toIgnore("abc", true));
+
+		assertTrue(ignoreRules.toIgnore("abbc", false));
+		assertTrue(ignoreRules.toIgnore("abbc", true));
+
+		assertTrue(ignoreRules.toIgnore("aabc", false));
+		assertTrue(ignoreRules.toIgnore("aabc", true));
+
+		assertFalse(ignoreRules.toIgnore("cab", false));
+		assertFalse(ignoreRules.toIgnore("cab", true));
+	}
+
+	public void testGlobalPatternWithTwoStars() throws Exception {
+		List<String> lines = new ArrayList<String>();
+		lines.add("a*c*e");
+		final Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);
+
+		assertTrue(ignoreRules.toIgnore("ace", false));
+		assertTrue(ignoreRules.toIgnore("ace", true));
+
+		assertTrue(ignoreRules.toIgnore("abcde", false));
+		assertTrue(ignoreRules.toIgnore("abcde", true));
+
+		assertTrue(ignoreRules.toIgnore("aHellocWorlde", false));
+		assertTrue(ignoreRules.toIgnore("aHellocWorlde", true));
+
+		assertFalse(ignoreRules.toIgnore("ae", false));
+		assertFalse(ignoreRules.toIgnore("ae", true));
+	}
+
+	public void testGlobalPatternWithDots() throws Exception {
+		List<String> lines = new ArrayList<String>();
+		lines.add("*.tar.gz");
+		final Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);
+
+		assertTrue(ignoreRules.toIgnore("test.tar.gz", false));
+		assertTrue(ignoreRules.toIgnore("test.tar.gz", true));
+
+		assertTrue(ignoreRules.toIgnore(".tar.gz", false));
+		assertTrue(ignoreRules.toIgnore(".tar.gz", true));
+
+		assertFalse(ignoreRules.toIgnore("test", false));
+		assertFalse(ignoreRules.toIgnore("test", true));
+
+		// test that "." isn't handled as "any character"
+		assertFalse(ignoreRules.toIgnore(".tarogz", false));
+		assertFalse(ignoreRules.toIgnore(".tarogz", true));
+	}
+
+	public void testGlobalPatternDirectoryOnlyRule() throws Exception {
+		List<String> lines = new ArrayList<String>();
+		lines.add("a/");
+		final Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);
+
+		assertTrue(ignoreRules.toIgnore("a", true));
+		assertFalse(ignoreRules.toIgnore("a", false));
+
+		final Rules ignoreRulesA = ignoreRules.getRulesForSubDirectory("a");
+		assertSame(Rules.IGNORE_ALL, ignoreRulesA);
+
+		final Rules ignoreRulesB = ignoreRules.getRulesForSubDirectory("b");
+		assertTrue(ignoreRulesB.toIgnore("a", true));
+		assertFalse(ignoreRulesB.toIgnore("a", false));
+
+		final Rules ignoreRulesBA = ignoreRulesB.getRulesForSubDirectory("a");
+		assertSame(Rules.IGNORE_ALL, ignoreRulesBA);
+
+	}
+
+	public void testSimpleFilePathPattern() throws Exception {
+		List<String> lines = new ArrayList<String>();
+		lines.add("a/b/c");
+		final Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);
+		assertFalse(ignoreRules.toIgnore("a", true));
+		assertFalse(ignoreRules.toIgnore("a", false));
+		assertFalse(ignoreRules.toIgnore("b", true));
+		assertFalse(ignoreRules.toIgnore("b", false));
+		assertFalse(ignoreRules.toIgnore("c", true));
+		assertFalse(ignoreRules.toIgnore("c", false));
+
+		final Rules ignoreRulesA = ignoreRules.getRulesForSubDirectory("a");
+		assertFalse(ignoreRulesA.toIgnore("a", true));
+		assertFalse(ignoreRulesA.toIgnore("a", false));
+		assertFalse(ignoreRulesA.toIgnore("b", true));
+		assertFalse(ignoreRulesA.toIgnore("b", false));
+		assertFalse(ignoreRulesA.toIgnore("c", true));
+		assertFalse(ignoreRulesA.toIgnore("c", false));
+
+		final Rules ignoreRulesAB = ignoreRulesA.getRulesForSubDirectory("b");
+		assertFalse(ignoreRulesAB.toIgnore("a", true));
+		assertFalse(ignoreRulesAB.toIgnore("a", false));
+		assertFalse(ignoreRulesAB.toIgnore("b", true));
+		assertFalse(ignoreRulesAB.toIgnore("b", false));
+		assertTrue(ignoreRulesAB.toIgnore("c", true));
+		assertTrue(ignoreRulesAB.toIgnore("c", false));
+
+		final Rules ignoreRulesABA = ignoreRulesAB.getRulesForSubDirectory("a");
+		assertSame(Rules.IGNORE_NOTHING, ignoreRulesABA);
+
+		final Rules ignoreRulesABB = ignoreRulesAB.getRulesForSubDirectory("b");
+		assertSame(Rules.IGNORE_NOTHING, ignoreRulesABB);
+
+		final Rules ignoreRulesABC = ignoreRulesAB.getRulesForSubDirectory("c");
+		assertSame(Rules.IGNORE_ALL, ignoreRulesABC);
+	}
+
+	public void testFilePathPatternDirectoryOnlyRule() throws Exception {
+		List<String> lines = new ArrayList<String>();
+		lines.add("a/b/c/");
+		final Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);
+		assertFalse(ignoreRules.toIgnore("a", true));
+		assertFalse(ignoreRules.toIgnore("a", false));
+		assertFalse(ignoreRules.toIgnore("b", true));
+		assertFalse(ignoreRules.toIgnore("b", false));
+		assertFalse(ignoreRules.toIgnore("c", true));
+		assertFalse(ignoreRules.toIgnore("c", false));
+
+		final Rules ignoreRulesA = ignoreRules.getRulesForSubDirectory("a");
+		assertFalse(ignoreRulesA.toIgnore("a", true));
+		assertFalse(ignoreRulesA.toIgnore("a", false));
+		assertFalse(ignoreRulesA.toIgnore("b", true));
+		assertFalse(ignoreRulesA.toIgnore("b", false));
+		assertFalse(ignoreRulesA.toIgnore("c", true));
+		assertFalse(ignoreRulesA.toIgnore("c", false));
+
+		final Rules ignoreRulesAB = ignoreRulesA.getRulesForSubDirectory("b");
+		assertFalse(ignoreRulesAB.toIgnore("a", true));
+		assertFalse(ignoreRulesAB.toIgnore("a", false));
+		assertFalse(ignoreRulesAB.toIgnore("b", true));
+		assertFalse(ignoreRulesAB.toIgnore("b", false));
+		assertTrue(ignoreRulesAB.toIgnore("c", true));
+		assertFalse(ignoreRulesAB.toIgnore("c", false));
+
+		final Rules ignoreRulesABA = ignoreRulesAB.getRulesForSubDirectory("a");
+		assertSame(Rules.IGNORE_NOTHING, ignoreRulesABA);
+
+		final Rules ignoreRulesABB = ignoreRulesAB.getRulesForSubDirectory("b");
+		assertSame(Rules.IGNORE_NOTHING, ignoreRulesABB);
+
+		final Rules ignoreRulesABC = ignoreRulesAB.getRulesForSubDirectory("c");
+		assertSame(Rules.IGNORE_ALL, ignoreRulesABC);
+	}
+
+	public void testShortPathPattern() throws Exception {
+		List<String> lines = new ArrayList<String>();
+		lines.add("/alpha");
+		final Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);
+		assertTrue(ignoreRules.toIgnore("alpha", true));
+		assertTrue(ignoreRules.toIgnore("alpha", false));
+
+		final Rules ignoreRulesAlpha = ignoreRules
+				.getRulesForSubDirectory("alpha");
+		assertSame(Rules.IGNORE_ALL, ignoreRulesAlpha);
+
+		final Rules ignoreRulesBeta = ignoreRules
+				.getRulesForSubDirectory("beta");
+		assertSame(Rules.IGNORE_NOTHING, ignoreRulesBeta);
+	}
+
+	public void testShortDirectoryPathPattern() throws Exception {
+		List<String> lines = new ArrayList<String>();
+		lines.add("/alpha/");
+		final Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);
+		assertTrue(ignoreRules.toIgnore("alpha", true));
+		assertFalse(ignoreRules.toIgnore("alpha", false));
+
+		final Rules ignoreRulesAlpha = ignoreRules
+				.getRulesForSubDirectory("alpha");
+		assertSame(Rules.IGNORE_ALL, ignoreRulesAlpha);
+
+		final Rules ignoreRulesBeta = ignoreRules
+				.getRulesForSubDirectory("beta");
+		assertSame(Rules.IGNORE_NOTHING, ignoreRulesBeta);
+	}
+
+	public void testShortPathPatternWithStar() throws Exception {
+		List<String> lines = new ArrayList<String>();
+		lines.add("/.*");
+		final Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);
+
+		assertTrue(ignoreRules.toIgnore(".test", true));
+		assertTrue(ignoreRules.toIgnore(".test", false));
+
+		assertFalse(ignoreRules.toIgnore("test", true));
+		assertFalse(ignoreRules.toIgnore("test", false));
+
+		final Rules ignoreRulesDotTest = ignoreRules
+				.getRulesForSubDirectory(".test");
+		assertSame(Rules.IGNORE_ALL, ignoreRulesDotTest);
+
+		final Rules ignoreRulesTest = ignoreRules
+				.getRulesForSubDirectory("test");
+		assertSame(Rules.IGNORE_NOTHING, ignoreRulesTest);
+	}
+
+	public void testPathPatternWith2Times2Stars() throws Exception {
+		final List<String> lines = new ArrayList<String>();
+		lines.add("he*wor*d/*.*");
+		final Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);
+
+		assertFalse(ignoreRules.toIgnore("hello", true));
+		assertFalse(ignoreRules.toIgnore("hello", false));
+		final Rules ignoreRulesHello = ignoreRules
+				.getRulesForSubDirectory("hello");
+		assertSame(Rules.IGNORE_NOTHING, ignoreRulesHello);
+
+		assertFalse(ignoreRules.toIgnore("helloworld", true));
+		assertFalse(ignoreRules.toIgnore("helloworld", false));
+		final Rules ignoreRulesHelloWorld = ignoreRules
+				.getRulesForSubDirectory("helloworld");
+		assertNotSame(Rules.IGNORE_NOTHING, ignoreRulesHelloWorld);
+
+		assertTrue(ignoreRulesHelloWorld.toIgnore("test.txt", true));
+		assertTrue(ignoreRulesHelloWorld.toIgnore("test.txt", false));
+
+		assertFalse(ignoreRulesHelloWorld.toIgnore("test", true));
+		assertFalse(ignoreRulesHelloWorld.toIgnore("test", false));
+
+		final Rules ignoreRulesTestTxt = ignoreRulesHelloWorld
+				.getRulesForSubDirectory("test.txt");
+		assertSame(Rules.IGNORE_ALL, ignoreRulesTestTxt);
+
+		final Rules ignoreRulesTest = ignoreRulesHelloWorld
+				.getRulesForSubDirectory("test");
+		assertSame(Rules.IGNORE_NOTHING, ignoreRulesTest);
+	}
+
+	public void testEmptyIgnoreList() throws Exception {
+		final List<String> lines = Collections.emptyList();
+		final Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);
+		assertSame(Rules.IGNORE_NOTHING, ignoreRules);
+	}
+
+	public void testOnlyOneNegatedIgnore() throws Exception {
+		final List<String> lines = new ArrayList<String>();
+		lines.add("!a");
+		final Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);
+		assertSame(Rules.IGNORE_NOTHING, ignoreRules);
+	}
+
+	public void testOnlyThreeNegatedIgnores() throws Exception {
+		final List<String> lines = new ArrayList<String>();
+		lines.add("!a");
+		lines.add("!a/b/c");
+		lines.add("!b*");
+		final Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);
+		assertSame(Rules.IGNORE_NOTHING, ignoreRules);
+	}
+
+	public void testNegatedIgnoreCase1() throws Exception {
+		final List<String> lines = new ArrayList<String>();
+		lines.add("/a");
+		lines.add("!b");
+		final Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);
+		final Rules ignoreRulesA = ignoreRules.getRulesForSubDirectory("a");
+		final Rules ignoreRulesAB = ignoreRulesA.getRulesForSubDirectory("b");
+		final Rules ignoreRulesB = ignoreRules.getRulesForSubDirectory("b");
+		final Rules ignoreRulesC = ignoreRules.getRulesForSubDirectory("c");
+		assertSame(Rules.IGNORE_NOTHING, ignoreRulesB);
+		assertSame(Rules.IGNORE_NOTHING, ignoreRulesAB);
+		assertSame(Rules.IGNORE_NOTHING, ignoreRulesC);
+		assertTrue(ignoreRules.toIgnore("a", true));
+		assertTrue(ignoreRules.toIgnore("a", false));
+		assertTrue(ignoreRulesA.toIgnore("c", true));
+		assertTrue(ignoreRulesA.toIgnore("c", false));
+	}
+
+	public void testExceptionOfException() throws Exception {
+		final List<String> lines = new ArrayList<String>();
+		lines.add("*.*");
+		lines.add("!*.c");
+		lines.add("a.c");
+		final Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);
+		assertTrue(ignoreRules.toIgnore("b.txt", false));
+		assertTrue(ignoreRules.toIgnore("b.txt", true));
+		assertTrue(ignoreRules.toIgnore("a.c", false));
+		assertTrue(ignoreRules.toIgnore("a.c", true));
+		assertFalse(ignoreRules.toIgnore("b.c", false));
+		assertFalse(ignoreRules.toIgnore("b.c", true));
+	}
+
+	public void testComplexCase() throws Exception {
+		final List<String> lines = new ArrayList<String>();
+		lines.add("*");
+		lines.add("!/alpha/src");
+		lines.add("*~");
+		final Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);
+		assertTrue(ignoreRules.toIgnore("beta", true));
+		assertTrue(ignoreRules.toIgnore("alpha", true));
+		final Rules ignoreRulesAlpha = ignoreRules
+				.getRulesForSubDirectory("alpha");
+		final Rules ignoreRulesAlphaBin = ignoreRulesAlpha
+				.getRulesForSubDirectory("bin");
+		final Rules ignoreRulesAlphaSrc = ignoreRulesAlpha
+				.getRulesForSubDirectory("src");
+		assertSame(Rules.IGNORE_ALL, ignoreRulesAlphaBin);
+		assertFalse(ignoreRulesAlphaSrc.toIgnore("com", true));
+		assertFalse(ignoreRulesAlphaSrc.toIgnore("b.java", false));
+		assertTrue(ignoreRulesAlphaSrc.toIgnore("b.java~", true));
+	}
+
+	private class IgnoreRulesFactory {
+		private RuleListToObjectConverter converter = new RuleListToObjectConverter();
+
+		private IgnoreRuleListFactory listFactory = new IgnoreRuleListFactory();
+
+		/**
+		 * @param ignoreFileLines
+		 *            the lines of a ignore file like .gitignore.
+		 * @return a immutable IgnoreRules object.
+		 * @throws InvalidPatternException
+		 */
+		public Rules createIgnoreRulesFromLines(Iterable<String> ignoreFileLines)
+				throws InvalidPatternException {
+			final List<Rule> rules = listFactory
+					.createIgnoreRuleList(ignoreFileLines);
+			return converter.createIgnoreRules(rules.iterator());
+		}
+
+	}
+
+}
-- 
1.5.4.3

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [JGIT PATCH v3 11/23] Added the class PathNotInProjectDirectoryException.
  2008-05-23 20:34 [JGIT PATCH v3 0/23] Implementation of a file tree iteration using ignore rules Florian Koeberle
                   ` (9 preceding siblings ...)
  2008-05-23 20:34 ` [JGIT PATCH v3 10/23] Added test class OverallIgnoreRulestest Florian Koeberle
@ 2008-05-23 20:34 ` Florian Koeberle
  2008-05-23 20:34 ` [JGIT PATCH v3 12/23] Added the class AddRuleListFactory Florian Koeberle
                   ` (14 subsequent siblings)
  25 siblings, 0 replies; 41+ messages in thread
From: Florian Koeberle @ 2008-05-23 20:34 UTC (permalink / raw)
  To: git; +Cc: Florian Koeberle

Signed-off-by: Florian Koeberle <florianskarten@web.de>
---
 .../errors/PathNotInProjectDirectoryException.java |   25 ++++++++++++++++++++
 1 files changed, 25 insertions(+), 0 deletions(-)
 create mode 100644 org.spearce.jgit/src/org/spearce/jgit/errors/PathNotInProjectDirectoryException.java

diff --git a/org.spearce.jgit/src/org/spearce/jgit/errors/PathNotInProjectDirectoryException.java b/org.spearce.jgit/src/org/spearce/jgit/errors/PathNotInProjectDirectoryException.java
new file mode 100644
index 0000000..a406aef
--- /dev/null
+++ b/org.spearce.jgit/src/org/spearce/jgit/errors/PathNotInProjectDirectoryException.java
@@ -0,0 +1,25 @@
+/*
+ *  Copyright (C) 2008 Florian Köberle
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public
+ *  License, version 2, as published by the Free Software Foundation.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ */
+package org.spearce.jgit.errors;
+
+/**
+ * Thrown when a path wasn't in the project directory, but expected to be.
+ * 
+ */
+public class PathNotInProjectDirectoryException extends
+		IllegalArgumentException {
+}
-- 
1.5.4.3

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [JGIT PATCH v3 12/23] Added the class AddRuleListFactory.
  2008-05-23 20:34 [JGIT PATCH v3 0/23] Implementation of a file tree iteration using ignore rules Florian Koeberle
                   ` (10 preceding siblings ...)
  2008-05-23 20:34 ` [JGIT PATCH v3 11/23] Added the class PathNotInProjectDirectoryException Florian Koeberle
@ 2008-05-23 20:34 ` Florian Koeberle
  2008-05-23 20:34 ` [JGIT PATCH v3 13/23] Formatted Constants class Florian Koeberle
                   ` (13 subsequent siblings)
  25 siblings, 0 replies; 41+ messages in thread
From: Florian Koeberle @ 2008-05-23 20:34 UTC (permalink / raw)
  To: git; +Cc: Florian Koeberle

Signed-off-by: Florian Koeberle <florianskarten@web.de>
---
 .../jgit/treewalk/rules/AddRuleListFactory.java    |   75 ++++++++++++++++++++
 1 files changed, 75 insertions(+), 0 deletions(-)
 create mode 100644 org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/AddRuleListFactory.java

diff --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
new file mode 100644
index 0000000..5c385c1
--- /dev/null
+++ b/org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/AddRuleListFactory.java
@@ -0,0 +1,75 @@
+/*
+ *  Copyright (C) 2008 Florian Köberle
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public
+ *  License, version 2, as published by the Free Software Foundation.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ */
+package org.spearce.jgit.treewalk.rules;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.spearce.jgit.errors.InvalidPatternException;
+import org.spearce.jgit.errors.PathNotInProjectDirectoryException;
+
+class AddRuleListFactory {
+
+	private static String getRelativeUnixPath(File projectDirectory, File file)
+			throws PathNotInProjectDirectoryException, IOException {
+		final StringBuilder resultBuilder = new StringBuilder();
+		File currentFile = file.getCanonicalFile();
+		while (!currentFile.equals(projectDirectory)) {
+			if (resultBuilder.length() > 0) {
+				resultBuilder.insert(0, '/');
+			}
+			resultBuilder.insert(0, currentFile.getName());
+			currentFile = currentFile.getParentFile();
+			if (currentFile == null) {
+				throw new PathNotInProjectDirectoryException();
+			}
+		}
+		return resultBuilder.toString();
+	}
+
+	List<Rule> createRuleList(File projectDirectory, File workingDirectory,
+			List<String> filePatternsOfAddCommand)
+			throws PathNotInProjectDirectoryException, IOException,
+			InvalidPatternException {
+
+		final String workingDirectoryPath = getRelativeUnixPath(
+				projectDirectory, workingDirectory);
+
+		final List<Rule> ruleList = new ArrayList<Rule>(
+				filePatternsOfAddCommand.size());
+		for (String pattern : filePatternsOfAddCommand) {
+			boolean matchDirectoriesOnly = false;
+			if (pattern.endsWith(File.separator)) {
+				pattern = pattern.substring(0, pattern.length() - 1);
+				matchDirectoriesOnly = true;
+			}
+			pattern = pattern.replace(File.separatorChar, '/');
+			if (!"".equals(workingDirectoryPath)) {
+				pattern = workingDirectoryPath + "/" + pattern;
+
+			}
+			final FilePattern filePattern = new FilePathPattern(pattern, true,
+					matchDirectoriesOnly);
+			final Rule rule = new Rule(false, filePattern);
+			ruleList.add(rule);
+
+		}
+		return ruleList;
+	}
+}
-- 
1.5.4.3

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [JGIT PATCH v3 13/23] Formatted Constants class.
  2008-05-23 20:34 [JGIT PATCH v3 0/23] Implementation of a file tree iteration using ignore rules Florian Koeberle
                   ` (11 preceding siblings ...)
  2008-05-23 20:34 ` [JGIT PATCH v3 12/23] Added the class AddRuleListFactory Florian Koeberle
@ 2008-05-23 20:34 ` Florian Koeberle
  2008-05-23 20:34 ` [JGIT PATCH v3 14/23] Added constant REPOSITORY_DIRECTORY_NAME to " Florian Koeberle
                   ` (12 subsequent siblings)
  25 siblings, 0 replies; 41+ messages in thread
From: Florian Koeberle @ 2008-05-23 20:34 UTC (permalink / raw)
  To: git; +Cc: Florian Koeberle

Signed-off-by: Florian Koeberle <florianskarten@web.de>
---
 .../src/org/spearce/jgit/lib/Constants.java        |   14 ++++++++------
 1 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Constants.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Constants.java
index 0c83cf2..febf469 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/Constants.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Constants.java
@@ -201,8 +201,9 @@ public final class Constants {
 
 	/**
 	 * Convert an OBJ_* type constant to a TYPE_* type constant.
-	 *
-	 * @param typeCode the type code, from a pack representation.
+	 * 
+	 * @param typeCode
+	 *            the type code, from a pack representation.
 	 * @return the canonical string name of this type.
 	 */
 	public static String typeString(final int typeCode) {
@@ -223,10 +224,11 @@ public final class Constants {
 	/**
 	 * Convert an OBJ_* type constant to an ASCII encoded string constant.
 	 * <p>
-	 * The ASCII encoded string is often the canonical representation of
-	 * the type within a loose object header, or within a tag header.
-	 *
-	 * @param typeCode the type code, from a pack representation.
+	 * The ASCII encoded string is often the canonical representation of the
+	 * type within a loose object header, or within a tag header.
+	 * 
+	 * @param typeCode
+	 *            the type code, from a pack representation.
 	 * @return the canonical ASCII encoded name of this type.
 	 */
 	public static byte[] encodedTypeString(final int typeCode) {
-- 
1.5.4.3

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [JGIT PATCH v3 14/23] Added constant REPOSITORY_DIRECTORY_NAME to Constants class.
  2008-05-23 20:34 [JGIT PATCH v3 0/23] Implementation of a file tree iteration using ignore rules Florian Koeberle
                   ` (12 preceding siblings ...)
  2008-05-23 20:34 ` [JGIT PATCH v3 13/23] Formatted Constants class Florian Koeberle
@ 2008-05-23 20:34 ` Florian Koeberle
  2008-05-23 20:34 ` [JGIT PATCH v3 15/23] Added class AddRulesFactory Florian Koeberle
                   ` (11 subsequent siblings)
  25 siblings, 0 replies; 41+ messages in thread
From: Florian Koeberle @ 2008-05-23 20:34 UTC (permalink / raw)
  To: git; +Cc: Florian Koeberle

Signed-off-by: Florian Koeberle <florianskarten@web.de>
---
 .../src/org/spearce/jgit/lib/Constants.java        |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Constants.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Constants.java
index febf469..7444d1d 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/Constants.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Constants.java
@@ -182,6 +182,12 @@ public final class Constants {
 	public static final String TAGS_PREFIX = "refs/tags";
 
 	/**
+	 * The name of the repository directory in the project directory. Project
+	 * directory means here the tree under version control.
+	 */
+	public static final String REPOSITORY_DIRECTORY_NAME = ".git";
+
+	/**
 	 * Create a new digest function for objects.
 	 * 
 	 * @return a new digest object.
-- 
1.5.4.3

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [JGIT PATCH v3 15/23] Added class AddRulesFactory.
  2008-05-23 20:34 [JGIT PATCH v3 0/23] Implementation of a file tree iteration using ignore rules Florian Koeberle
                   ` (13 preceding siblings ...)
  2008-05-23 20:34 ` [JGIT PATCH v3 14/23] Added constant REPOSITORY_DIRECTORY_NAME to " Florian Koeberle
@ 2008-05-23 20:34 ` Florian Koeberle
  2008-05-23 20:34 ` [JGIT PATCH v3 16/23] Added the class LightFileTreeIterator and a test for it Florian Koeberle
                   ` (10 subsequent siblings)
  25 siblings, 0 replies; 41+ messages in thread
From: Florian Koeberle @ 2008-05-23 20:34 UTC (permalink / raw)
  To: git; +Cc: Florian Koeberle

Signed-off-by: Florian Koeberle <florianskarten@web.de>
---
 .../jgit/treewalk/rules/AddRulesFactory.java       |   90 ++++++++++++++++++++
 1 files changed, 90 insertions(+), 0 deletions(-)
 create mode 100644 org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/AddRulesFactory.java

diff --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
new file mode 100644
index 0000000..3daa928
--- /dev/null
+++ b/org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/AddRulesFactory.java
@@ -0,0 +1,90 @@
+package org.spearce.jgit.treewalk.rules;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.spearce.jgit.errors.InvalidPatternException;
+import org.spearce.jgit.errors.PathNotInProjectDirectoryException;
+import static org.spearce.jgit.lib.Constants.REPOSITORY_DIRECTORY_NAME;
+
+/**
+ * This class is designed to serve the needs of someone who want to implement a
+ * git-add command and needs to determine the files to add.
+ * 
+ */
+public class AddRulesFactory {
+	private final RuleListToObjectConverter converter = new RuleListToObjectConverter();
+
+	private final IgnoreRuleListFactory ignoreRuleListFactory = new IgnoreRuleListFactory();
+
+	private final AddRuleListFactory addRuleListFactory = new AddRuleListFactory();
+
+	/**
+	 * @param workTreeDirectory
+	 *            The directory with the files of the project under version
+	 *            control.
+	 * @param workingDirectory
+	 *            a directory within the workTreeDirectory.
+	 * @param filePatternsOfAddCommand
+	 *            the file patterns passed to the add command.
+	 * @return a {@link Rules} containing the specified rules, the .gitignore
+	 *         and the .git/info/exclude rules.
+	 * @throws InvalidPatternException
+	 *             if a pattern is invalid.
+	 * @throws PathNotInProjectDirectoryException
+	 *             if the directory workingDirectory is not in workTreeDirectory
+	 * @throws IOException
+	 *             for some reasons.
+	 */
+	public Rules createRules(File workTreeDirectory, File workingDirectory,
+			List<String> filePatternsOfAddCommand)
+			throws InvalidPatternException, PathNotInProjectDirectoryException,
+			IOException {
+		final Rule gitDirectoryIgnoreRule = createGitDirectoryIgnoreRule();
+		final File gitDirectory = new File(workTreeDirectory,
+				REPOSITORY_DIRECTORY_NAME);
+		final List<Rule> ignoreRuleListFromFiles = createExcludeRules(
+				workTreeDirectory, gitDirectory);
+		final List<Rule> includeRules = addRuleListFactory.createRuleList(
+				workTreeDirectory, workingDirectory, filePatternsOfAddCommand);
+		final List<Rule> ruleList = new ArrayList<Rule>();
+
+		ruleList.add(gitDirectoryIgnoreRule);
+		ruleList.addAll(ignoreRuleListFromFiles);
+		ruleList.addAll(includeRules);
+		ruleList.add(new Rule(true, FilePattern.MATCH_ALWAYS));
+
+		return converter.createIgnoreRules(ruleList.iterator());
+	}
+
+	private List<Rule> createExcludeRules(File projectDirectory,
+			File gitDirectory) throws InvalidPatternException {
+		final List<File> possibleIgnoreFiles = new ArrayList<File>(2);
+		possibleIgnoreFiles.add(new File(projectDirectory, ".gitignore"));
+		possibleIgnoreFiles.add(new File(new File(gitDirectory, "info"),
+				"exclude"));
+
+		final List<File> ignoreFiles = new ArrayList<File>();
+		for (File possibleIgnoreFile : possibleIgnoreFiles) {
+			if (possibleIgnoreFile.isFile()) {
+				ignoreFiles.add(possibleIgnoreFile);
+			}
+		}
+
+		try {
+			return ignoreRuleListFactory.createIgnoreRuleList(ignoreFiles);
+		} catch (FileNotFoundException e) {
+			throw new RuntimeException("unexpected removal of ignore files", e);
+		}
+	}
+
+	private Rule createGitDirectoryIgnoreRule() throws InvalidPatternException {
+		final FilePattern gitDirectoryPattern = new FilePathPattern(
+				REPOSITORY_DIRECTORY_NAME, true, true);
+		final Rule gitDirectoryIgnoreRule = new Rule(true, gitDirectoryPattern);
+		return gitDirectoryIgnoreRule;
+	}
+}
-- 
1.5.4.3

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [JGIT PATCH v3 16/23] Added the class LightFileTreeIterator and a test for it.
  2008-05-23 20:34 [JGIT PATCH v3 0/23] Implementation of a file tree iteration using ignore rules Florian Koeberle
                   ` (14 preceding siblings ...)
  2008-05-23 20:34 ` [JGIT PATCH v3 15/23] Added class AddRulesFactory Florian Koeberle
@ 2008-05-23 20:34 ` Florian Koeberle
  2008-05-31 10:03   ` [JGIT PATCH v3.1 " Florian Koeberle
  2008-05-23 20:34 ` [JGIT PATCH v3 17/23] Added class LightFileTreeIterable Florian Koeberle
                   ` (9 subsequent siblings)
  25 siblings, 1 reply; 41+ messages in thread
From: Florian Koeberle @ 2008-05-23 20:34 UTC (permalink / raw)
  To: git; +Cc: Florian Koeberle

Signed-off-by: Florian Koeberle <florianskarten@web.de>
---
 .../jgit/treewalk/LightFileTreeIteratorTest.java   |  114 ++++++++++++++++++++
 .../jgit/treewalk/LightFileTreeIterator.java       |  112 +++++++++++++++++++
 2 files changed, 226 insertions(+), 0 deletions(-)
 create mode 100644 org.spearce.jgit.test/tst/org/spearce/jgit/treewalk/LightFileTreeIteratorTest.java
 create mode 100644 org.spearce.jgit/src/org/spearce/jgit/treewalk/LightFileTreeIterator.java

diff --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
new file mode 100644
index 0000000..f937182
--- /dev/null
+++ b/org.spearce.jgit.test/tst/org/spearce/jgit/treewalk/LightFileTreeIteratorTest.java
@@ -0,0 +1,114 @@
+/*
+ *  Copyright (C) 2008 Florian Köberle
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public
+ *  License, version 2, as published by the Free Software Foundation.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ */
+package org.spearce.jgit.treewalk;
+
+import java.io.File;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.spearce.jgit.treewalk.rules.Rules;
+
+import junit.framework.TestCase;
+
+public class LightFileTreeIteratorTest extends TestCase {
+	private String DIRECTORY_A_NAME = "a";
+
+	private String DIRECTORY_AB_NAME = "b";
+
+	private File projectDirectory;
+
+	private File fileB;
+
+	private File directoryA;
+
+	private File directoryAB;
+
+	private File fileABA;
+
+	private File directoryAC;
+
+	private File fileACA;
+
+	private File fileACB;
+
+	@Override
+	protected void setUp() throws Exception {
+		this.projectDirectory = File.createTempFile("FileTreeIteratorTest", "");
+		projectDirectory.delete();
+		projectDirectory.mkdir();
+		projectDirectory.deleteOnExit();
+
+		this.directoryA = new File(projectDirectory, DIRECTORY_A_NAME);
+		directoryA.mkdir();
+
+		this.directoryAB = new File(directoryA, DIRECTORY_AB_NAME);
+		directoryAB.mkdir();
+
+		this.fileABA = new File(directoryAB, "a.y");
+		fileABA.createNewFile();
+
+		this.directoryAC = new File(directoryA, "c");
+		this.directoryAC.mkdir();
+
+		this.fileACA = new File(directoryAC, "a.x");
+		fileACA.createNewFile();
+
+		this.fileACB = new File(directoryAC, "b.y");
+		fileACB.createNewFile();
+
+		this.fileB = new File(projectDirectory, "b.x");
+		fileB.createNewFile();
+	}
+
+	public void testFileTreeIterator() {
+		final Iterator<File> iterator = new LightFileTreeIterator(
+				projectDirectory, Rules.IGNORE_NOTHING, false);
+		final Set<File> actualPathes = new HashSet<File>();
+		while (iterator.hasNext()) {
+			final File next = iterator.next();
+			assertFalse(actualPathes.contains(next));
+			actualPathes.add(next);
+		}
+
+		final Set<File> expectedPathes = new HashSet<File>();
+		expectedPathes.add(directoryA);
+		expectedPathes.add(fileB);
+		expectedPathes.add(directoryAB);
+		expectedPathes.add(fileABA);
+		expectedPathes.add(directoryAC);
+		expectedPathes.add(fileACA);
+		expectedPathes.add(fileACB);
+		assertEquals(expectedPathes, actualPathes);
+
+	}
+
+	public void testFileTreeIteratorWithIgnoreAllRules() {
+		final Iterator<File> iterator = new LightFileTreeIterator(
+				projectDirectory, Rules.IGNORE_ALL, false);
+		final Set<File> actualPathes = new HashSet<File>();
+		while (iterator.hasNext()) {
+			final File next = iterator.next();
+			assertFalse(actualPathes.contains(next));
+			actualPathes.add(next);
+		}
+
+		assertEquals(0, actualPathes.size());
+
+	}
+
+}
diff --git a/org.spearce.jgit/src/org/spearce/jgit/treewalk/LightFileTreeIterator.java b/org.spearce.jgit/src/org/spearce/jgit/treewalk/LightFileTreeIterator.java
new file mode 100644
index 0000000..45fb167
--- /dev/null
+++ b/org.spearce.jgit/src/org/spearce/jgit/treewalk/LightFileTreeIterator.java
@@ -0,0 +1,112 @@
+/*
+ *  Copyright (C) 2008 Florian Köberle
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public
+ *  License, version 2, as published by the Free Software Foundation.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ */
+package org.spearce.jgit.treewalk;
+
+import java.io.File;
+import java.util.EmptyStackException;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.Stack;
+
+import org.spearce.jgit.treewalk.rules.Rules;
+
+class LightFileTreeIterator implements Iterator<File> {
+	private final Stack<File> remainingPathes;
+
+	private final Stack<Directory> remainingDirectories;
+
+	/**
+	 * Creates a new Iterator which allows to iterate over the content of the
+	 * specified rootDirectory. The rootDirectory itself is never included.
+	 * 
+	 * @param rootDirectory
+	 *            the directory tree to iterate over.
+	 * @param ignoreRules
+	 *            defines which paths are included and which aren't.
+	 * @param includeRootDirectory
+	 *            the iterator will return the rootDirectory if this is flag is
+	 *            true.
+	 */
+	LightFileTreeIterator(File rootDirectory, Rules ignoreRules,
+			boolean includeRootDirectory) {
+		remainingPathes = new Stack<File>();
+		if (includeRootDirectory) {
+			remainingPathes.add(rootDirectory);
+		}
+		remainingDirectories = new Stack<Directory>();
+		remainingDirectories.add(new Directory(rootDirectory, ignoreRules));
+	}
+
+	public boolean hasNext() {
+		findMorePathesIfNessesary();
+		return !remainingPathes.empty();
+	}
+
+	void findMorePathesIfNessesary() {
+		if (remainingPathes.isEmpty()) {
+			findMorePathes();
+		}
+	}
+
+	void findMorePathes() {
+		while (!remainingDirectories.isEmpty() && remainingPathes.isEmpty()) {
+			final Directory directory = remainingDirectories.pop();
+			final File[] pathes = directory.path.listFiles();
+			for (File path : pathes) {
+				final boolean fileIsDirectory = path.isDirectory();
+				if (fileIsDirectory) {
+					final Rules subDirectoryIgnoreRules = directory.ignoreRules
+							.getRulesForSubDirectory(path.getName());
+					if (subDirectoryIgnoreRules != Rules.IGNORE_ALL) {
+						final Directory subDirectory = new Directory(path,
+								subDirectoryIgnoreRules);
+						remainingDirectories.add(subDirectory);
+					}
+				}
+				if (!directory.ignoreRules.toIgnore(path.getName(),
+						fileIsDirectory)) {
+					remainingPathes.add(path);
+				}
+			}
+		}
+	}
+
+	public File next() {
+		findMorePathesIfNessesary();
+		try {
+			return remainingPathes.pop();
+		} catch (EmptyStackException e) {
+			throw new NoSuchElementException();
+		}
+	}
+
+	public void remove() {
+		throw new UnsupportedOperationException();
+	}
+
+	private class Directory {
+		final File path;
+
+		final Rules ignoreRules;
+
+		Directory(File path, Rules ignoreRules) {
+			this.path = path;
+			this.ignoreRules = ignoreRules;
+		}
+	}
+
+}
-- 
1.5.4.3

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [JGIT PATCH v3 17/23] Added class LightFileTreeIterable.
  2008-05-23 20:34 [JGIT PATCH v3 0/23] Implementation of a file tree iteration using ignore rules Florian Koeberle
                   ` (15 preceding siblings ...)
  2008-05-23 20:34 ` [JGIT PATCH v3 16/23] Added the class LightFileTreeIterator and a test for it Florian Koeberle
@ 2008-05-23 20:34 ` Florian Koeberle
  2008-05-23 20:34 ` [JGIT PATCH v3 18/23] Added path related constants to the Constants class Florian Koeberle
                   ` (8 subsequent siblings)
  25 siblings, 0 replies; 41+ messages in thread
From: Florian Koeberle @ 2008-05-23 20:34 UTC (permalink / raw)
  To: git; +Cc: Florian Koeberle

Signed-off-by: Florian Koeberle <florianskarten@web.de>
---
 .../jgit/treewalk/LightFileTreeIterable.java       |   59 ++++++++++++++++++++
 1 files changed, 59 insertions(+), 0 deletions(-)
 create mode 100644 org.spearce.jgit/src/org/spearce/jgit/treewalk/LightFileTreeIterable.java

diff --git a/org.spearce.jgit/src/org/spearce/jgit/treewalk/LightFileTreeIterable.java b/org.spearce.jgit/src/org/spearce/jgit/treewalk/LightFileTreeIterable.java
new file mode 100644
index 0000000..5768f78
--- /dev/null
+++ b/org.spearce.jgit/src/org/spearce/jgit/treewalk/LightFileTreeIterable.java
@@ -0,0 +1,59 @@
+/*
+ *  Copyright (C) 2008 Florian Köberle
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public
+ *  License, version 2, as published by the Free Software Foundation.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ */
+package org.spearce.jgit.treewalk;
+
+import java.io.File;
+import java.util.Iterator;
+
+import org.spearce.jgit.treewalk.rules.Rules;
+
+/**
+ * Use this class to iterate over some by rules determined files in a project
+ * directory.
+ * 
+ */
+public class LightFileTreeIterable implements Iterable<File> {
+	private final File projectDirectory;
+
+	private final Rules ignoreRules;
+
+	private final boolean includeRootDirectory;
+
+	/**
+	 * 
+	 * @param workTreeDirectory
+	 *            directory with the files which are under version control.
+	 * @param rules
+	 *            a {@link Rules} instance which is used to determine which file
+	 *            are included and which not.
+	 * @param includeWorkTreeDirectory
+	 *            determines if the iterators should return the
+	 *            workTreeDirectory
+	 */
+	public LightFileTreeIterable(File workTreeDirectory, Rules rules,
+			boolean includeWorkTreeDirectory) {
+		this.projectDirectory = workTreeDirectory;
+		this.ignoreRules = rules;
+		this.includeRootDirectory = includeWorkTreeDirectory;
+	}
+
+	public Iterator<File> iterator() {
+		return new LightFileTreeIterator(projectDirectory, ignoreRules,
+				includeRootDirectory);
+	}
+
+}
-- 
1.5.4.3

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [JGIT PATCH v3 18/23] Added path related constants to the Constants class.
  2008-05-23 20:34 [JGIT PATCH v3 0/23] Implementation of a file tree iteration using ignore rules Florian Koeberle
                   ` (16 preceding siblings ...)
  2008-05-23 20:34 ` [JGIT PATCH v3 17/23] Added class LightFileTreeIterable Florian Koeberle
@ 2008-05-23 20:34 ` Florian Koeberle
  2008-05-23 20:34 ` [JGIT PATCH v3 19/23] Added WorkTree class which can be constructed over Repository Florian Koeberle
                   ` (7 subsequent siblings)
  25 siblings, 0 replies; 41+ messages in thread
From: Florian Koeberle @ 2008-05-23 20:34 UTC (permalink / raw)
  To: git; +Cc: Florian Koeberle

---
 .../src/org/spearce/jgit/lib/Constants.java        |   10 ++++++++++
 1 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Constants.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Constants.java
index 7444d1d..38b0626 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/Constants.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Constants.java
@@ -188,6 +188,16 @@ public final class Constants {
 	public static final String REPOSITORY_DIRECTORY_NAME = ".git";
 
 	/**
+	 * Contains the name of the objects directory in the repository directory.
+	 */
+	public static final String OBJECTS_DIRECTORY_NAME = "objects";
+
+	/**
+	 * Contains the name of the refs directory in the repository directory.
+	 */
+	public static final String REFS_DIRECTORY_NAME = "refs";
+
+	/**
 	 * Create a new digest function for objects.
 	 * 
 	 * @return a new digest object.
-- 
1.5.4.3

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [JGIT PATCH v3 19/23] Added WorkTree class which can be constructed over Repository.
  2008-05-23 20:34 [JGIT PATCH v3 0/23] Implementation of a file tree iteration using ignore rules Florian Koeberle
                   ` (17 preceding siblings ...)
  2008-05-23 20:34 ` [JGIT PATCH v3 18/23] Added path related constants to the Constants class Florian Koeberle
@ 2008-05-23 20:34 ` Florian Koeberle
  2008-06-06  0:23   ` Robin Rosenberg
  2008-05-23 20:34 ` [JGIT PATCH v3 20/23] Added the class NoGitRepositoryFoundException Florian Koeberle
                   ` (6 subsequent siblings)
  25 siblings, 1 reply; 41+ messages in thread
From: Florian Koeberle @ 2008-05-23 20:34 UTC (permalink / raw)
  To: git; +Cc: Florian Koeberle

---
 .../src/org/spearce/jgit/lib/Repository.java       |   57 +++++++++++++++++
 .../src/org/spearce/jgit/lib/WorkTree.java         |   67 ++++++++++++++++++++
 2 files changed, 124 insertions(+), 0 deletions(-)
 create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/WorkTree.java

diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
index 54edc8a..86817c9 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
@@ -1157,4 +1157,61 @@ public class Repository {
 	public File getWorkDir() {
 		return getDirectory().getParentFile();
 	}
+
+	/**
+	 * Setup HEAD and "master" refs for a new repository.
+	 * 
+	 * @param remoteBranch
+	 *            The remote branch to start with
+	 * @param branch
+	 *            The local branch to configure, initially starting at
+	 *            remoteBranch
+	 * @return the commit references by the new HEAD
+	 * @throws IOException
+	 */
+	public Commit setupHEADRef(final String remoteBranch, final String branch)
+			throws IOException {
+		Commit mapCommit = mapCommit(remoteBranch);
+		String refName = Constants.HEADS_PREFIX + "/" + branch;
+		LockFile masterRef = lockRef(refName);
+		try {
+			masterRef.write(mapCommit.getCommitId());
+			masterRef.commit();
+		} finally {
+			masterRef.unlock();
+		}
+		writeSymref(Constants.HEAD, refName);
+		return mapCommit;
+	}
+
+	/**
+	 * Creates a new {@link WorkTree} and initialize a repository for it.
+	 * 
+	 * @param workTreeDirectory
+	 *            the directory with the project files.
+	 * @return a new {@link WorkTree} with a new and open {@link Repository}.
+	 * @throws IOException
+	 *             thrown by {@link Repository#create()}
+	 */
+	public static WorkTree createWorkTree(File workTreeDirectory)
+			throws IOException {
+		final File gitDirectory = new File(workTreeDirectory,
+				Constants.REPOSITORY_DIRECTORY_NAME);
+		if (gitDirectory.exists()) {
+			throw new IllegalArgumentException(
+					"Repository exists in given project directory.");
+		}
+		final Repository repository = new Repository(gitDirectory);
+		try {
+			repository.create();
+			return new WorkTree(workTreeDirectory, repository);
+		} catch (RuntimeException e) {
+			repository.close();
+			throw e;
+		} catch (IOException e) {
+			repository.close();
+			throw e;
+		}
+	}
+
 }
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/WorkTree.java b/org.spearce.jgit/src/org/spearce/jgit/lib/WorkTree.java
new file mode 100644
index 0000000..14bdda0
--- /dev/null
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/WorkTree.java
@@ -0,0 +1,67 @@
+/*
+ *  Copyright (C) 2008 Florian Köberle
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public
+ *  License, version 2, as published by the Free Software Foundation.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ */
+package org.spearce.jgit.lib;
+
+import java.io.File;
+
+/**
+ * Represents a work tree controlled by git. Use {@link Repository} in order to
+ * create an object of this class.
+ * 
+ */
+public class WorkTree {
+	private final File directory;
+
+	private final Repository repository;
+
+	/**
+	 * This constructor should be only used by the class {@link Repository}.
+	 * 
+	 * @param directory
+	 *            defines the value of the directory field.
+	 * @param repository
+	 *            defines the value of the repository field.
+	 */
+	WorkTree(File directory, Repository repository) {
+		this.directory = directory;
+		this.repository = repository;
+	}
+
+	/**
+	 * 
+	 * @return the directory which contains the files of the project. Usually
+	 *         this directory contain a .git directory with the repository.
+	 */
+	public File getDirectory() {
+		return directory;
+	}
+
+	/**
+	 * @return the {@link Repository} object of the project.
+	 */
+	public Repository getRepository() {
+		return repository;
+	}
+
+	/**
+	 * Closes the git repository of this project.
+	 */
+	public void closeRepository() {
+		repository.close();
+	}
+
+}
-- 
1.5.4.3

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [JGIT PATCH v3 20/23] Added the class NoGitRepositoryFoundException.
  2008-05-23 20:34 [JGIT PATCH v3 0/23] Implementation of a file tree iteration using ignore rules Florian Koeberle
                   ` (18 preceding siblings ...)
  2008-05-23 20:34 ` [JGIT PATCH v3 19/23] Added WorkTree class which can be constructed over Repository Florian Koeberle
@ 2008-05-23 20:34 ` Florian Koeberle
  2008-06-06  0:23   ` Robin Rosenberg
  2008-05-23 20:34 ` [JGIT PATCH v3 21/23] Formatted Repository class Florian Koeberle
                   ` (5 subsequent siblings)
  25 siblings, 1 reply; 41+ messages in thread
From: Florian Koeberle @ 2008-05-23 20:34 UTC (permalink / raw)
  To: git; +Cc: Florian Koeberle

Signed-off-by: Florian Koeberle <florianskarten@web.de>
---
 .../jgit/errors/NoGitRepositoryFoundException.java |   28 ++++++++++++++++++++
 1 files changed, 28 insertions(+), 0 deletions(-)
 create mode 100644 org.spearce.jgit/src/org/spearce/jgit/errors/NoGitRepositoryFoundException.java

diff --git a/org.spearce.jgit/src/org/spearce/jgit/errors/NoGitRepositoryFoundException.java b/org.spearce.jgit/src/org/spearce/jgit/errors/NoGitRepositoryFoundException.java
new file mode 100644
index 0000000..a0c6e83
--- /dev/null
+++ b/org.spearce.jgit/src/org/spearce/jgit/errors/NoGitRepositoryFoundException.java
@@ -0,0 +1,28 @@
+package org.spearce.jgit.errors;
+
+import java.io.File;
+
+/**
+ * No git repository could be found for a file or directory.
+ */
+public class NoGitRepositoryFoundException extends Exception {
+	private final File fileWeSearchedRepositoryFor;
+
+	/**
+	 * @param fileWeSearchedRepositoryFor
+	 *            the file for which a repository was searched.
+	 */
+	public NoGitRepositoryFoundException(final File fileWeSearchedRepositoryFor) {
+		super(String.format("No repository found for file '%s'",
+				fileWeSearchedRepositoryFor));
+		this.fileWeSearchedRepositoryFor = fileWeSearchedRepositoryFor;
+	}
+
+	/**
+	 * @return the file searched for.
+	 */
+	public File getFileWeSearchedRepositoryFor() {
+		return fileWeSearchedRepositoryFor;
+	}
+
+}
-- 
1.5.4.3

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [JGIT PATCH v3 21/23] Formatted Repository class.
  2008-05-23 20:34 [JGIT PATCH v3 0/23] Implementation of a file tree iteration using ignore rules Florian Koeberle
                   ` (19 preceding siblings ...)
  2008-05-23 20:34 ` [JGIT PATCH v3 20/23] Added the class NoGitRepositoryFoundException Florian Koeberle
@ 2008-05-23 20:34 ` Florian Koeberle
  2008-06-06  0:23   ` Robin Rosenberg
  2008-05-23 20:34 ` [JGIT PATCH v3 22/23] Added findWorkTree method to " Florian Koeberle
                   ` (4 subsequent siblings)
  25 siblings, 1 reply; 41+ messages in thread
From: Florian Koeberle @ 2008-05-23 20:34 UTC (permalink / raw)
  To: git; +Cc: Florian Koeberle

Signed-off-by: Florian Koeberle <florianskarten@web.de>
---
 .../src/org/spearce/jgit/lib/Repository.java       |  345 +++++++++++---------
 1 files changed, 192 insertions(+), 153 deletions(-)

diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
index 86817c9..06e686f 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
@@ -38,24 +38,25 @@ import org.spearce.jgit.util.FS;
  * Represents a Git repository. A repository holds all objects and refs used for
  * managing source code (could by any type of file, but source code is what
  * SCM's are typically used for).
- *
+ * 
  * In Git terms all data is stored in GIT_DIR, typically a directory called
  * .git. A work tree is maintained unless the repository is a bare repository.
  * Typically the .git directory is located at the root of the work dir.
- *
+ * 
  * <ul>
  * <li>GIT_DIR
- * 	<ul>
- * 		<li>objects/ - objects</li>
- * 		<li>refs/ - tags and heads</li>
- * 		<li>config - configuration</li>
- * 		<li>info/ - more configurations</li>
- * 	</ul>
+ * <ul>
+ * <li>objects/ - objects</li>
+ * <li>refs/ - tags and heads</li>
+ * <li>config - configuration</li>
+ * <li>info/ - more configurations</li>
+ * </ul>
  * </li>
  * </ul>
- *
- * This implementation only handles a subtly undocumented subset of git features.
- *
+ * 
+ * This implementation only handles a subtly undocumented subset of git
+ * features.
+ * 
  */
 public class Repository {
 	private static final String[] refSearchPaths = { "", "refs/",
@@ -80,7 +81,7 @@ public class Repository {
 
 	/**
 	 * Construct a representation of this git repo managing a Git repository.
-	 *
+	 * 
 	 * @param d
 	 *            GIT_DIR
 	 * @throws IOException
@@ -109,7 +110,8 @@ public class Repository {
 			objectsDirs = readObjectsDirs(FS.resolve(gitDir, "objects"),
 					new ArrayList<File>()).toArray(new File[0]);
 		} catch (IOException e) {
-			IOException ex = new IOException("Cannot find all object dirs for " + gitDir);
+			IOException ex = new IOException("Cannot find all object dirs for "
+					+ gitDir);
 			ex.initCause(e);
 			throw ex;
 		}
@@ -135,12 +137,13 @@ public class Repository {
 			scanForPacks();
 	}
 
-	private Collection<File> readObjectsDirs(File objectsDir, Collection<File> ret) throws IOException {
+	private Collection<File> readObjectsDirs(File objectsDir,
+			Collection<File> ret) throws IOException {
 		ret.add(objectsDir);
 		final File altFile = FS.resolve(objectsDir, "info/alternates");
 		if (altFile.exists()) {
 			BufferedReader ar = new BufferedReader(new FileReader(altFile));
-			for (String alt=ar.readLine(); alt!=null; alt=ar.readLine()) {
+			for (String alt = ar.readLine(); alt != null; alt = ar.readLine()) {
 				readObjectsDirs(FS.resolve(objectsDir, alt), ret);
 			}
 			ar.close();
@@ -151,7 +154,7 @@ public class Repository {
 	/**
 	 * Create a new Git repository initializing the necessary files and
 	 * directories.
-	 *
+	 * 
 	 * @throws IOException
 	 */
 	public void create() throws IOException {
@@ -213,15 +216,15 @@ public class Repository {
 	 * to the alternative repo will be returned. If the object is not yet store
 	 * a usable path in this repo will be returned. It is assumed that callers
 	 * will look for objects in a pack first.
-	 *
+	 * 
 	 * @param objectId
 	 * @return suggested file name
 	 */
 	public File toFile(final AnyObjectId objectId) {
 		final String n = objectId.toString();
-		String d=n.substring(0, 2);
-		String f=n.substring(2);
-		for (int i=0; i<objectsDirs.length; ++i) {
+		String d = n.substring(0, 2);
+		String f = n.substring(2);
+		for (int i = 0; i < objectsDirs.length; ++i) {
 			File ret = new File(new File(objectsDirs[i], d), f);
 			if (ret.exists())
 				return ret;
@@ -253,9 +256,8 @@ public class Repository {
 	 *         object, or null if the object does not exist.
 	 * @throws IOException
 	 */
-	public ObjectLoader openObject(final AnyObjectId id)
-			throws IOException {
-		return openObject(new WindowCursor(),id);
+	public ObjectLoader openObject(final AnyObjectId id) throws IOException {
+		return openObject(new WindowCursor(), id);
 	}
 
 	/**
@@ -281,7 +283,8 @@ public class Repository {
 					// This shouldn't happen unless the pack was corrupted
 					// after we opened it or the VM runs out of memory. This is
 					// a know problem with memory mapped I/O in java and have
-					// been noticed with JDK < 1.6. Tell the gc that now is a good
+					// been noticed with JDK < 1.6. Tell the gc that now is a
+					// good
 					// time to collect and try once more.
 					try {
 						curs.release();
@@ -327,14 +330,16 @@ public class Repository {
 	}
 
 	/**
-	 * Access a Commit object using a symbolic reference. This reference may
-	 * be a SHA-1 or ref in combination with a number of symbols translating
-	 * from one ref or SHA1-1 to another, such as HEAD^ etc.
-	 *
-	 * @param revstr a reference to a git commit object
+	 * Access a Commit object using a symbolic reference. This reference may be
+	 * a SHA-1 or ref in combination with a number of symbols translating from
+	 * one ref or SHA1-1 to another, such as HEAD^ etc.
+	 * 
+	 * @param revstr
+	 *            a reference to a git commit object
 	 * @return a Commit named by the specified string
-	 * @throws IOException for I/O error or unexpected object type.
-	 *
+	 * @throws IOException
+	 *             for I/O error or unexpected object type.
+	 * 
 	 * @see #resolve(String)
 	 */
 	public Commit mapCommit(final String revstr) throws IOException {
@@ -344,14 +349,16 @@ public class Repository {
 
 	/**
 	 * Access any type of Git object by id and
-	 *
+	 * 
 	 * @param id
 	 *            SHA-1 of object to read
-	 * @param refName optional, only relevant for simple tags
+	 * @param refName
+	 *            optional, only relevant for simple tags
 	 * @return The Git object if found or null
 	 * @throws IOException
 	 */
-	public Object mapObject(final ObjectId id, final String refName) throws IOException {
+	public Object mapObject(final ObjectId id, final String refName)
+			throws IOException {
 		final ObjectLoader or = openObject(id);
 		final byte[] raw = or.getBytes();
 		if (or.getType() == Constants.OBJ_TREE)
@@ -367,9 +374,11 @@ public class Repository {
 
 	/**
 	 * Access a Commit by SHA'1 id.
+	 * 
 	 * @param id
 	 * @return Commit or null
-	 * @throws IOException for I/O error or unexpected object type.
+	 * @throws IOException
+	 *             for I/O error or unexpected object type.
 	 */
 	public Commit mapCommit(final ObjectId id) throws IOException {
 		final ObjectLoader or = openObject(id);
@@ -387,14 +396,15 @@ public class Repository {
 	}
 
 	/**
-	 * Access a Tree object using a symbolic reference. This reference may
-	 * be a SHA-1 or ref in combination with a number of symbols translating
-	 * from one ref or SHA1-1 to another, such as HEAD^{tree} etc.
-	 *
-	 * @param revstr a reference to a git commit object
+	 * Access a Tree object using a symbolic reference. This reference may be a
+	 * SHA-1 or ref in combination with a number of symbols translating from one
+	 * ref or SHA1-1 to another, such as HEAD^{tree} etc.
+	 * 
+	 * @param revstr
+	 *            a reference to a git commit object
 	 * @return a Tree named by the specified string
 	 * @throws IOException
-	 *
+	 * 
 	 * @see #resolve(String)
 	 */
 	public Tree mapTree(final String revstr) throws IOException {
@@ -404,9 +414,11 @@ public class Repository {
 
 	/**
 	 * Access a Tree by SHA'1 id.
+	 * 
 	 * @param id
 	 * @return Tree or null
-	 * @throws IOException for I/O error or unexpected object type.
+	 * @throws IOException
+	 *             for I/O error or unexpected object type.
 	 */
 	public Tree mapTree(final ObjectId id) throws IOException {
 		final ObjectLoader or = openObject(id);
@@ -421,22 +433,25 @@ public class Repository {
 		throw new IncorrectObjectTypeException(id, Constants.TYPE_TREE);
 	}
 
-	private Tree makeTree(final ObjectId id, final byte[] raw) throws IOException {
+	private Tree makeTree(final ObjectId id, final byte[] raw)
+			throws IOException {
 		Tree ret = new Tree(this, id, raw);
 		return ret;
 	}
 
-	private Tag makeTag(final ObjectId id, final String refName, final byte[] raw) {
+	private Tag makeTag(final ObjectId id, final String refName,
+			final byte[] raw) {
 		Tag ret = new Tag(this, id, refName, raw);
 		return ret;
 	}
 
 	/**
 	 * Access a tag by symbolic name.
-	 *
+	 * 
 	 * @param revstr
 	 * @return a Tag or null
-	 * @throws IOException on I/O error or unexpected type
+	 * @throws IOException
+	 *             on I/O error or unexpected type
 	 */
 	public Tag mapTag(String revstr) throws IOException {
 		final ObjectId id = resolve(revstr);
@@ -445,12 +460,15 @@ public class Repository {
 
 	/**
 	 * Access a Tag by SHA'1 id
+	 * 
 	 * @param refName
 	 * @param id
 	 * @return Commit or null
-	 * @throws IOException for I/O error or unexpected object type.
+	 * @throws IOException
+	 *             for I/O error or unexpected object type.
 	 */
-	public Tag mapTag(final String refName, final ObjectId id) throws IOException {
+	public Tag mapTag(final String refName, final ObjectId id)
+			throws IOException {
 		final ObjectLoader or = openObject(id);
 		if (or == null)
 			return null;
@@ -462,8 +480,9 @@ public class Repository {
 
 	/**
 	 * Get a locked handle to a ref suitable for updating or creating.
-	 *
-	 * @param ref name to lock
+	 * 
+	 * @param ref
+	 *            name to lock
 	 * @return a locked ref
 	 * @throws IOException
 	 */
@@ -492,27 +511,29 @@ public class Repository {
 
 	/**
 	 * Parse a git revision string and return an object id.
-	 *
+	 * 
 	 * Currently supported is combinations of these.
 	 * <ul>
-	 *  <li>SHA-1 - a SHA-1</li>
-	 *  <li>refs/... - a ref name</li>
-	 *  <li>ref^n - nth parent reference</li>
-	 *  <li>ref~n - distance via parent reference</li>
-	 *  <li>ref@{n} - nth version of ref</li>
-	 *  <li>ref^{tree} - tree references by ref</li>
-	 *  <li>ref^{commit} - commit references by ref</li>
+	 * <li>SHA-1 - a SHA-1</li>
+	 * <li>refs/... - a ref name</li>
+	 * <li>ref^n - nth parent reference</li>
+	 * <li>ref~n - distance via parent reference</li>
+	 * <li>ref@{n} - nth version of ref</li>
+	 * <li>ref^{tree} - tree references by ref</li>
+	 * <li>ref^{commit} - commit references by ref</li>
 	 * </ul>
-	 *
+	 * 
 	 * Not supported is
 	 * <ul>
 	 * <li>timestamps in reflogs, ref@{full or relative timestamp}</li>
 	 * <li>abbreviated SHA-1's</li>
 	 * </ul>
-	 *
-	 * @param revstr A git object references expression
+	 * 
+	 * @param revstr
+	 *            A git object references expression
 	 * @return an ObjectId
-	 * @throws IOException on serious errors
+	 * @throws IOException
+	 *             on serious errors
 	 */
 	public ObjectId resolve(final String revstr) throws IOException {
 		char[] rev = revstr.toCharArray();
@@ -522,7 +543,7 @@ public class Repository {
 			switch (rev[i]) {
 			case '^':
 				if (refId == null) {
-					String refstr = new String(rev,0,i);
+					String refstr = new String(rev, 0, i);
 					refId = resolveSimple(refstr);
 					if (refId == null)
 						return null;
@@ -542,23 +563,24 @@ public class Repository {
 						int j;
 						ref = mapObject(refId, null);
 						if (!(ref instanceof Commit))
-							throw new IncorrectObjectTypeException(refId, Constants.TYPE_COMMIT);
-						for (j=i+1; j<rev.length; ++j) {
+							throw new IncorrectObjectTypeException(refId,
+									Constants.TYPE_COMMIT);
+						for (j = i + 1; j < rev.length; ++j) {
 							if (!Character.isDigit(rev[j]))
 								break;
 						}
-						String parentnum = new String(rev, i+1, j-i-1);
+						String parentnum = new String(rev, i + 1, j - i - 1);
 						int pnum = Integer.parseInt(parentnum);
 						if (pnum != 0)
-							refId = ((Commit)ref).getParentIds()[pnum - 1];
+							refId = ((Commit) ref).getParentIds()[pnum - 1];
 						i = j - 1;
 						break;
 					case '{':
 						int k;
 						String item = null;
-						for (k=i+2; k<rev.length; ++k) {
+						for (k = i + 2; k < rev.length; ++k) {
 							if (rev[k] == '}') {
-								item = new String(rev, i+2, k-i-2);
+								item = new String(rev, i + 2, k - i - 2);
 								break;
 							}
 						}
@@ -567,44 +589,43 @@ public class Repository {
 							if (item.equals("tree")) {
 								ref = mapObject(refId, null);
 								while (ref instanceof Tag) {
-									Tag t = (Tag)ref;
+									Tag t = (Tag) ref;
 									refId = t.getObjId();
 									ref = mapObject(refId, null);
 								}
 								if (ref instanceof Treeish)
-									refId = ((Treeish)ref).getTreeId();
+									refId = ((Treeish) ref).getTreeId();
 								else
-									throw new IncorrectObjectTypeException(refId,  Constants.TYPE_TREE);
-							}
-							else if (item.equals("commit")) {
+									throw new IncorrectObjectTypeException(
+											refId, Constants.TYPE_TREE);
+							} else if (item.equals("commit")) {
 								ref = mapObject(refId, null);
 								while (ref instanceof Tag) {
-									Tag t = (Tag)ref;
+									Tag t = (Tag) ref;
 									refId = t.getObjId();
 									ref = mapObject(refId, null);
 								}
 								if (!(ref instanceof Commit))
-									throw new IncorrectObjectTypeException(refId,  Constants.TYPE_COMMIT);
-							}
-							else if (item.equals("blob")) {
+									throw new IncorrectObjectTypeException(
+											refId, Constants.TYPE_COMMIT);
+							} else if (item.equals("blob")) {
 								ref = mapObject(refId, null);
 								while (ref instanceof Tag) {
-									Tag t = (Tag)ref;
+									Tag t = (Tag) ref;
 									refId = t.getObjId();
 									ref = mapObject(refId, null);
 								}
 								if (!(ref instanceof byte[]))
-									throw new IncorrectObjectTypeException(refId,  Constants.TYPE_COMMIT);
-							}
-							else if (item.equals("")) {
+									throw new IncorrectObjectTypeException(
+											refId, Constants.TYPE_COMMIT);
+							} else if (item.equals("")) {
 								ref = mapObject(refId, null);
 								if (ref instanceof Tag)
-									refId = ((Tag)ref).getObjId();
+									refId = ((Tag) ref).getObjId();
 								else {
 									// self
 								}
-							}
-							else
+							} else
 								throw new RevisionSyntaxException(revstr);
 						else
 							throw new RevisionSyntaxException(revstr);
@@ -612,22 +633,24 @@ public class Repository {
 					default:
 						ref = mapObject(refId, null);
 						if (ref instanceof Commit)
-							refId = ((Commit)ref).getParentIds()[0];
+							refId = ((Commit) ref).getParentIds()[0];
 						else
-							throw new IncorrectObjectTypeException(refId,  Constants.TYPE_COMMIT);
-						
+							throw new IncorrectObjectTypeException(refId,
+									Constants.TYPE_COMMIT);
+
 					}
 				} else {
 					ref = mapObject(refId, null);
 					if (ref instanceof Commit)
-						refId = ((Commit)ref).getParentIds()[0];
+						refId = ((Commit) ref).getParentIds()[0];
 					else
-						throw new IncorrectObjectTypeException(refId,  Constants.TYPE_COMMIT);
+						throw new IncorrectObjectTypeException(refId,
+								Constants.TYPE_COMMIT);
 				}
 				break;
 			case '~':
 				if (ref == null) {
-					String refstr = new String(rev,0,i);
+					String refstr = new String(rev, 0, i);
 					refId = resolveSimple(refstr);
 					ref = mapCommit(refId);
 				}
@@ -636,10 +659,10 @@ public class Repository {
 					if (!Character.isDigit(rev[l]))
 						break;
 				}
-				String distnum = new String(rev, i+1, l-i-1);
+				String distnum = new String(rev, i + 1, l - i - 1);
 				int dist = Integer.parseInt(distnum);
 				while (dist >= 0) {
-					refId = ((Commit)ref).getParentIds()[0];
+					refId = ((Commit) ref).getParentIds()[0];
 					ref = mapCommit(refId);
 					--dist;
 				}
@@ -648,14 +671,16 @@ public class Repository {
 			case '@':
 				int m;
 				String time = null;
-				for (m=i+2; m<rev.length; ++m) {
+				for (m = i + 2; m < rev.length; ++m) {
 					if (rev[m] == '}') {
-						time = new String(rev, i+2, m-i-2);
+						time = new String(rev, i + 2, m - i - 2);
 						break;
 					}
 				}
 				if (time != null)
-					throw new RevisionSyntaxException("reflogs not yet supported by revision parser yet", revstr);
+					throw new RevisionSyntaxException(
+							"reflogs not yet supported by revision parser yet",
+							revstr);
 				i = m - 1;
 				break;
 			default:
@@ -707,10 +732,10 @@ public class Repository {
 		final String p = pack.getName();
 		final String i = idx.getName();
 		if (p.length() != 50 || !p.startsWith("pack-") || !p.endsWith(".pack"))
-		    throw new IllegalArgumentException("Not a valid pack " + pack);
+			throw new IllegalArgumentException("Not a valid pack " + pack);
 		if (i.length() != 49 || !i.startsWith("pack-") || !i.endsWith(".idx"))
-		    throw new IllegalArgumentException("Not a valid pack " + idx);
-		if (!p.substring(0,45).equals(i.substring(0,45)))
+			throw new IllegalArgumentException("Not a valid pack " + idx);
+		if (!p.substring(0, 45).equals(i.substring(0, 45)))
 			throw new IllegalArgumentException("Pack " + pack
 					+ "does not match index " + idx);
 
@@ -722,12 +747,11 @@ public class Repository {
 	}
 
 	/**
-	 * Scan the object dirs, including alternates for packs
-	 * to use.
+	 * Scan the object dirs, including alternates for packs to use.
 	 */
 	public void scanForPacks() {
 		final ArrayList<PackFile> p = new ArrayList<PackFile>();
-		for (int i=0; i<objectsDirs.length; ++i)
+		for (int i = 0; i < objectsDirs.length; ++i)
 			scanForPacks(new File(objectsDirs[i], "pack"), p);
 		final PackFile[] arr = new PackFile[p.size()];
 		p.toArray(arr);
@@ -758,14 +782,16 @@ public class Repository {
 		}
 	}
 
-    /**
-     * Writes a symref (e.g. HEAD) to disk
-     *
-     * @param name symref name
-     * @param target pointed to ref
-     * @throws IOException
-     */
-    public void writeSymref(final String name, final String target)
+	/**
+	 * Writes a symref (e.g. HEAD) to disk
+	 * 
+	 * @param name
+	 *            symref name
+	 * @param target
+	 *            pointed to ref
+	 * @throws IOException
+	 */
+	public void writeSymref(final String name, final String target)
 			throws IOException {
 		final byte[] content = ("ref: " + target + "\n").getBytes("UTF-8");
 		final LockFile lck = new LockFile(fileForRef(name));
@@ -802,7 +828,7 @@ public class Repository {
 				ObjectId id = packedRefs.get(name);
 				if (id != null)
 					return new Ref(name, id);
-				
+
 				// no packed ref found, return blank one
 				return new Ref(name, null);
 			}
@@ -840,12 +866,13 @@ public class Repository {
 	 * @throws IOException
 	 */
 	public String getPatch() throws IOException {
-		final File ptr = new File(getDirectory(),"patches/"+getBranch()+"/applied");
+		final File ptr = new File(getDirectory(), "patches/" + getBranch()
+				+ "/applied");
 		final BufferedReader br = new BufferedReader(new FileReader(ptr));
-		String last=null;
+		String last = null;
 		try {
 			String line;
-			while ((line=br.readLine())!=null) {
+			while ((line = br.readLine()) != null) {
 				last = line;
 			}
 		} finally {
@@ -859,7 +886,7 @@ public class Repository {
 	 * @throws IOException
 	 */
 	public String getFullBranch() throws IOException {
-		final File ptr = new File(getDirectory(),"HEAD");
+		final File ptr = new File(getDirectory(), "HEAD");
 		final BufferedReader br = new BufferedReader(new FileReader(ptr));
 		String ref;
 		try {
@@ -871,7 +898,7 @@ public class Repository {
 			ref = ref.substring(5);
 		return ref;
 	}
-	
+
 	/**
 	 * @return name of current branch.
 	 * @throws IOException
@@ -892,7 +919,7 @@ public class Repository {
 				ref = ref.substring(11);
 			return ref;
 		} catch (FileNotFoundException e) {
-			final File ptr = new File(getDirectory(),"head-name");
+			final File ptr = new File(getDirectory(), "head-name");
 			final BufferedReader br = new BufferedReader(new FileReader(ptr));
 			String ref;
 			try {
@@ -910,25 +937,27 @@ public class Repository {
 	public Collection<String> getBranches() {
 		return listRefs("heads");
 	}
-	
+
 	/**
 	 * @return the names of all refs (local and remotes branches, tags)
 	 */
 	public Collection<String> getAllRefs() {
 		return listRefs("");
 	}
-	
+
 	private Collection<String> listRefs(String refSubDir) {
 		// add / to end, unless empty
-		if (refSubDir.length() > 0 && refSubDir.charAt(refSubDir.length() -1 ) != '/')
+		if (refSubDir.length() > 0
+				&& refSubDir.charAt(refSubDir.length() - 1) != '/')
 			refSubDir += "/";
-		
-		Collection<String> branchesRaw = listFilesRecursively(new File(refsDir, refSubDir), null);
+
+		Collection<String> branchesRaw = listFilesRecursively(new File(refsDir,
+				refSubDir), null);
 		ArrayList<String> branches = new ArrayList<String>();
 		for (String b : branchesRaw) {
 			branches.add("refs/" + refSubDir + b);
 		}
-		
+
 		refreshPackedRefsCache();
 		Set<String> keySet = packedRefs.keySet();
 		for (String s : keySet)
@@ -944,22 +973,23 @@ public class Repository {
 		return listRefs("tags");
 	}
 
-	private Map<String,ObjectId> packedRefs = new HashMap<String,ObjectId>();
+	private Map<String, ObjectId> packedRefs = new HashMap<String, ObjectId>();
+
 	private long packedrefstime = 0;
 
 	private void refreshPackedRefsCache() {
 		if (!packedRefsFile.exists()) {
 			if (packedRefs.size() > 0)
-				packedRefs = new HashMap<String,ObjectId>();
+				packedRefs = new HashMap<String, ObjectId>();
 			return;
 		}
 		if (packedRefsFile.lastModified() == packedrefstime)
 			return;
-		Map<String,ObjectId> newPackedRefs = new HashMap<String,ObjectId>();
+		Map<String, ObjectId> newPackedRefs = new HashMap<String, ObjectId>();
 		FileReader fileReader = null;
 		try {
 			fileReader = new FileReader(packedRefsFile);
-			BufferedReader b=new BufferedReader(fileReader);
+			BufferedReader b = new BufferedReader(fileReader);
 			String p;
 			while ((p = b.readLine()) != null) {
 				if (p.charAt(0) == '#')
@@ -968,12 +998,12 @@ public class Repository {
 					continue;
 				}
 				int spos = p.indexOf(' ');
-				ObjectId id = ObjectId.fromString(p.substring(0,spos));
-				String name = p.substring(spos+1);
+				ObjectId id = ObjectId.fromString(p.substring(0, spos));
+				String name = p.substring(spos + 1);
 				newPackedRefs.put(name, id);
 			}
 		} catch (IOException e) {
-			throw new Error("Cannot read packed refs",e);
+			throw new Error("Cannot read packed refs", e);
 		} finally {
 			if (fileReader != null) {
 				try {
@@ -1016,13 +1046,17 @@ public class Repository {
 	 * @return applied patches in a map indexed on current commit id
 	 * @throws IOException
 	 */
-	public Map<ObjectId,StGitPatch> getAppliedPatches() throws IOException {
-		Map<ObjectId,StGitPatch> ret = new HashMap<ObjectId,StGitPatch>();
+	public Map<ObjectId, StGitPatch> getAppliedPatches() throws IOException {
+		Map<ObjectId, StGitPatch> ret = new HashMap<ObjectId, StGitPatch>();
 		if (isStGitMode()) {
-			File patchDir = new File(new File(getDirectory(),"patches"),getBranch());
-			BufferedReader apr = new BufferedReader(new FileReader(new File(patchDir,"applied")));
-			for (String patchName=apr.readLine(); patchName!=null; patchName=apr.readLine()) {
-				File topFile = new File(new File(new File(patchDir,"patches"), patchName), "top");
+			File patchDir = new File(new File(getDirectory(), "patches"),
+					getBranch());
+			BufferedReader apr = new BufferedReader(new FileReader(new File(
+					patchDir, "applied")));
+			for (String patchName = apr.readLine(); patchName != null; patchName = apr
+					.readLine()) {
+				File topFile = new File(new File(new File(patchDir, "patches"),
+						patchName), "top");
 				BufferedReader tfr = new BufferedReader(new FileReader(topFile));
 				String objectId = tfr.readLine();
 				ObjectId id = ObjectId.fromString(objectId);
@@ -1052,7 +1086,7 @@ public class Repository {
 		}
 		return ret;
 	}
-	
+
 	/** Clean up stale caches */
 	public void refreshFromDisk() {
 		packedRefs = null;
@@ -1075,7 +1109,7 @@ public class Repository {
 	static byte[] gitInternalSlash(byte[] bytes) {
 		if (File.separatorChar == '/')
 			return bytes;
-		for (int i=0; i<bytes.length; ++i)
+		for (int i = 0; i < bytes.length; ++i)
 			if (bytes[i] == File.separatorChar)
 				bytes[i] = '/';
 		return bytes;
@@ -1087,32 +1121,32 @@ public class Repository {
 	public RepositoryState getRepositoryState() {
 		if (new File(getWorkDir(), ".dotest").exists())
 			return RepositoryState.REBASING;
-		if (new File(gitDir,".dotest-merge").exists())
+		if (new File(gitDir, ".dotest-merge").exists())
 			return RepositoryState.REBASING_INTERACTIVE;
-		if (new File(gitDir,"MERGE_HEAD").exists())
+		if (new File(gitDir, "MERGE_HEAD").exists())
 			return RepositoryState.MERGING;
-		if (new File(gitDir,"BISECT_LOG").exists())
+		if (new File(gitDir, "BISECT_LOG").exists())
 			return RepositoryState.BISECTING;
 		return RepositoryState.SAFE;
 	}
 
 	/**
-	 * Check validty of a ref name. It must not contain character that has
-	 * a special meaning in a Git object reference expression. Some other
+	 * Check validty of a ref name. It must not contain character that has a
+	 * special meaning in a Git object reference expression. Some other
 	 * dangerous characters are also excluded.
-	 *
+	 * 
 	 * @param refName
-	 *
+	 * 
 	 * @return true if refName is a valid ref name
 	 */
 	public static boolean isValidRefName(final String refName) {
 		final int len = refName.length();
 		char p = '\0';
-		for (int i=0; i<len; ++i) {
+		for (int i = 0; i < len; ++i) {
 			char c = refName.charAt(i);
 			if (c <= ' ')
 				return false;
-			switch(c) {
+			switch (c) {
 			case '.':
 				if (i == 0)
 					return false;
@@ -1124,11 +1158,14 @@ public class Repository {
 			case '/':
 				if (i == 0)
 					return false;
-				if (i == len -1)
+				if (i == len - 1)
 					return false;
 				break;
-			case '~': case '^': case ':':
-			case '?': case '[':
+			case '~':
+			case '^':
+			case ':':
+			case '?':
+			case '[':
 				return false;
 			case '*':
 				return false;
@@ -1140,9 +1177,11 @@ public class Repository {
 
 	/**
 	 * String work dir and return normalized repository path
-	 *
-	 * @param wd Work dir
-	 * @param f File whose path shall be stripp off it's workdir
+	 * 
+	 * @param wd
+	 *            Work dir
+	 * @param f
+	 *            File whose path shall be stripp off it's workdir
 	 * @return normalized repository relative path
 	 */
 	public static String stripWorkDir(File wd, File f) {
-- 
1.5.4.3

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [JGIT PATCH v3 22/23] Added findWorkTree method to Repository class.
  2008-05-23 20:34 [JGIT PATCH v3 0/23] Implementation of a file tree iteration using ignore rules Florian Koeberle
                   ` (20 preceding siblings ...)
  2008-05-23 20:34 ` [JGIT PATCH v3 21/23] Formatted Repository class Florian Koeberle
@ 2008-05-23 20:34 ` Florian Koeberle
  2008-05-23 20:34 ` [JGIT PATCH v3 23/23] Added the test class AddCommandIterationTest Florian Koeberle
                   ` (3 subsequent siblings)
  25 siblings, 0 replies; 41+ messages in thread
From: Florian Koeberle @ 2008-05-23 20:34 UTC (permalink / raw)
  To: git; +Cc: Florian Koeberle

Signed-off-by: Florian Koeberle <florianskarten@web.de>
---
 .../src/org/spearce/jgit/lib/Repository.java       |   80 ++++++++++++++++++++
 1 files changed, 80 insertions(+), 0 deletions(-)

diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
index 06e686f..71e0e04 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
@@ -16,6 +16,11 @@
  */
 package org.spearce.jgit.lib;
 
+import static org.spearce.jgit.lib.Constants.HEAD;
+import static org.spearce.jgit.lib.Constants.OBJECTS_DIRECTORY_NAME;
+import static org.spearce.jgit.lib.Constants.REFS_DIRECTORY_NAME;
+import static org.spearce.jgit.lib.Constants.REPOSITORY_DIRECTORY_NAME;
+
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileNotFoundException;
@@ -29,6 +34,7 @@ import java.util.Map;
 import java.util.Set;
 
 import org.spearce.jgit.errors.IncorrectObjectTypeException;
+import org.spearce.jgit.errors.NoGitRepositoryFoundException;
 import org.spearce.jgit.errors.ObjectWritingException;
 import org.spearce.jgit.errors.RevisionSyntaxException;
 import org.spearce.jgit.stgit.StGitPatch;
@@ -1253,4 +1259,78 @@ public class Repository {
 		}
 	}
 
+	/**
+	 * Find the git repository for the current working directory.
+	 * 
+	 * @return a {@link Repository}.
+	 * @throws NoGitRepositoryFoundException
+	 *             if no git repository could be found for the current
+	 *             directory.
+	 * @throws IOException
+	 *             if not able to determine the absolute path of the current
+	 *             working directory.
+	 */
+	public static WorkTree findWorkTree() throws NoGitRepositoryFoundException,
+			IOException {
+		return findWorkTree(new File("."));
+	}
+
+	/**
+	 * Checks if a path is a valid git repository. Works similar like the method
+	 * is_git_directory from the original setup.c file.
+	 * 
+	 * @param directory
+	 *            the path which should be checked.
+	 * @return true if the path is a valid git repository.
+	 */
+	private static boolean isRepository(File directory) {
+		if (!directory.isDirectory()) {
+			return false;
+		}
+
+		final File objectDirectory = new File(directory, OBJECTS_DIRECTORY_NAME);
+		if (!objectDirectory.isDirectory()) {
+			return false;
+		}
+
+		final File refsDirectory = new File(directory, REFS_DIRECTORY_NAME);
+		if (!refsDirectory.isDirectory()) {
+			return false;
+		}
+
+		final File head = new File(directory, HEAD);
+		if (!hasValidateHeadRef(head)) {
+			return false;
+		}
+
+		return true;
+	}
+
+	/**
+	 * Checks for example if a path is a valid HEAD file.
+	 * 
+	 * @param path
+	 *            is the path of the HEAD file.
+	 * @return true if it has a valid head reference.
+	 */
+	private static final boolean hasValidateHeadRef(File path) {
+		return true; // TODO implement this method
+	}
+
+	private static WorkTree findWorkTree(final File directory)
+			throws IOException, NoGitRepositoryFoundException {
+		File currentDirectory = directory.getAbsoluteFile();
+		while (currentDirectory != null) {
+			final File commonGitDirectory = new File(directory,
+					REPOSITORY_DIRECTORY_NAME);
+			if (isRepository(commonGitDirectory))
+				return new WorkTree(currentDirectory, new Repository(
+						commonGitDirectory));
+			if (isRepository(currentDirectory))
+				return new WorkTree(null, new Repository(currentDirectory));
+			currentDirectory = currentDirectory.getParentFile();
+		}
+		throw new NoGitRepositoryFoundException(directory);
+	}
+
 }
-- 
1.5.4.3

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [JGIT PATCH v3 23/23] Added the test class AddCommandIterationTest.
  2008-05-23 20:34 [JGIT PATCH v3 0/23] Implementation of a file tree iteration using ignore rules Florian Koeberle
                   ` (21 preceding siblings ...)
  2008-05-23 20:34 ` [JGIT PATCH v3 22/23] Added findWorkTree method to " Florian Koeberle
@ 2008-05-23 20:34 ` Florian Koeberle
  2008-05-31 10:09   ` [JGIT PATCH v3.1 " Florian Koeberle
  2008-06-06  0:23   ` [JGIT PATCH v3 " Robin Rosenberg
  2008-05-31 10:17 ` [JGIT PATCH v3 0/23] Implementation of a file tree iteration using ignore rules Florian Köberle
                   ` (2 subsequent siblings)
  25 siblings, 2 replies; 41+ messages in thread
From: Florian Koeberle @ 2008-05-23 20:34 UTC (permalink / raw)
  To: git; +Cc: Florian Koeberle

Signed-off-by: Florian Koeberle <florianskarten@web.de>
---
 .../treewalk/rules/AddCommandIterationTest.java    |  321 ++++++++++++++++++++
 1 files changed, 321 insertions(+), 0 deletions(-)
 create mode 100644 org.spearce.jgit.test/tst/org/spearce/jgit/treewalk/rules/AddCommandIterationTest.java

diff --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
new file mode 100644
index 0000000..a96c880
--- /dev/null
+++ b/org.spearce.jgit.test/tst/org/spearce/jgit/treewalk/rules/AddCommandIterationTest.java
@@ -0,0 +1,321 @@
+/*
+ *  Copyright (C) 2008 Florian Köberle
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public
+ *  License, version 2, as published by the Free Software Foundation.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ */
+package org.spearce.jgit.treewalk.rules;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+import org.spearce.jgit.errors.InvalidPatternException;
+import org.spearce.jgit.errors.PathNotInProjectDirectoryException;
+import org.spearce.jgit.lib.Repository;
+import org.spearce.jgit.lib.WorkTree;
+import org.spearce.jgit.treewalk.LightFileTreeIterable;
+
+public class AddCommandIterationTest extends TestCase {
+
+	private WorkTree workTree;
+
+	private AddRulesFactory factory;
+
+	private Iterable<File> createIterable(File workingDirectory,
+			List<String> filePatternsOfAddCommand)
+			throws PathNotInProjectDirectoryException, InvalidPatternException,
+			IOException {
+		final Rules rules = factory.createRules(workTree.getDirectory(),
+				workingDirectory, filePatternsOfAddCommand);
+		return new LightFileTreeIterable(workTree.getDirectory(), rules, false);
+	}
+
+	@Override
+	protected void setUp() throws Exception {
+		final File projectDirectory = File.createTempFile("test", "");
+		projectDirectory.delete();
+		projectDirectory.mkdir();
+		projectDirectory.deleteOnExit();
+		this.workTree = Repository.createWorkTree(projectDirectory);
+		this.factory = new AddRulesFactory();
+	}
+
+	public void testNoPattern() throws Exception {
+		createFile("a.txt");
+		final Iterable<File> iterable = createIterable(workTree.getDirectory(),
+				Collections.<String> emptyList());
+		final Set<File> expectedPathes = Collections.emptySet();
+		assertIsValidIterable(iterable);
+		assertIterableReturnsSet(expectedPathes, iterable);
+	}
+
+	public void testTreePattern1() throws Exception {
+		final Set<File> expectedFiles = new HashSet<File>();
+		createFile("a.txt");
+		expectedFiles.add(createFile("a", "a.txt"));
+		expectedFiles.add(createFile("a", "a", "a.txt"));
+		expectedFiles.add(createFile("a", "b", "a.txt"));
+		createFile("a", "b", "a.c");
+
+		final File directoryA = new File(workTree.getDirectory(), "a");
+
+		final Iterable<File> iterable = createIterable(directoryA, Arrays
+				.asList("*.txt"));
+		assertIsValidIterable(iterable);
+		assertIterableReturnsSet(expectedFiles, iterable);
+	}
+
+	public void testTreePattern2() throws Exception {
+		final Set<File> expectedFiles = new HashSet<File>();
+		createFile("a.txt");
+		expectedFiles.add(createFile("a", "a.txt"));
+		expectedFiles.add(createFile("a", "a", "a.txt"));
+		expectedFiles.add(createFile("a", "b", "a.txt"));
+		createFile("a", "b", "a.c");
+
+		final Iterable<File> iterable = createIterable(workTree.getDirectory(),
+				Arrays.asList("a" + File.separator + "*.txt"));
+		assertIsValidIterable(iterable);
+		assertIterableReturnsSet(expectedFiles, iterable);
+	}
+
+	public void testSelectCompleteSubdirectory() throws Exception {
+		final Set<File> expectedPathes = new HashSet<File>();
+		final File directoryA = new File(workTree.getDirectory(), "a");
+		final File directoryAA = new File(directoryA, "a");
+		final File directoryAB = new File(directoryA, "b");
+		createFile("a.txt");
+		expectedPathes.add(directoryA);
+		expectedPathes.add(directoryAA);
+		expectedPathes.add(createFile("a", "a.txt"));
+		expectedPathes.add(createFile("a", "a", "a.txt"));
+		expectedPathes.add(directoryAB);
+		expectedPathes.add(createFile("a", "b", "a.txt"));
+		expectedPathes.add(createFile("a", "b", "a.c"));
+
+		final Iterable<File> iterable = createIterable(workTree.getDirectory(),
+				Arrays.asList("a"));
+
+		assertIsValidIterable(iterable);
+		assertIterableReturnsSet(expectedPathes, iterable);
+	}
+
+	public void testSelectTwoSubdirectories() throws Exception {
+		final Set<File> expectedPathes = new HashSet<File>();
+		final File directoryA = new File(workTree.getDirectory(), "a");
+		final File directoryAA = new File(directoryA, "a");
+		final File directoryAB = new File(directoryA, "b");
+		createFile("a.txt");
+		createFile("a", "a.txt");
+		expectedPathes.add(directoryAA);
+		expectedPathes.add(createFile("a", "a", "a.txt"));
+		expectedPathes.add(directoryAB);
+		expectedPathes.add(createFile("a", "b", "a.txt"));
+		expectedPathes.add(createFile("a", "b", "a.c"));
+
+		final List<String> patternList = new ArrayList<String>(2);
+		patternList.add("a" + File.separator + "a");
+		patternList.add("a" + File.separator + "b");
+		final Iterable<File> iterable = createIterable(workTree.getDirectory(),
+				patternList);
+
+		assertIsValidIterable(iterable);
+		assertIterableReturnsSet(expectedPathes, iterable);
+	}
+
+	public void testTwoDifferentSelects() throws Exception {
+		final Set<File> expectedPathes = new HashSet<File>();
+		final File directoryA = new File(workTree.getDirectory(), "a");
+		final File directoryAA = new File(directoryA, "a");
+		createFile("a.txt");
+		createFile("a", "a.txt");
+		expectedPathes.add(directoryAA);
+		expectedPathes.add(createFile("a", "a", "a.txt"));
+		expectedPathes.add(createFile("a", "b", "a.txt"));
+		expectedPathes.add(createFile("a", "b", "c", "a.txt"));
+		createFile("a", "b", "a.c");
+
+		final List<String> patternList = new ArrayList<String>(2);
+		patternList.add("a" + File.separator + "a");
+		patternList.add("a" + File.separator + "b" + File.separator + "*.txt");
+
+		final Iterable<File> iterable = createIterable(workTree.getDirectory(),
+				patternList);
+
+		assertIsValidIterable(iterable);
+		assertIterableReturnsSet(expectedPathes, iterable);
+	}
+
+	public void testRealisticExample() throws Exception {
+		final Set<File> expectedPathes = new HashSet<File>();
+
+		// write the .gitignore file
+		final File dotGitIgnoreFile = createFile(".gitignore");
+		final PrintWriter dotGitIgnoreFilePrinter = new PrintWriter(
+				dotGitIgnoreFile);
+		try {
+			dotGitIgnoreFilePrinter.println("/alpha/config.xml");
+			dotGitIgnoreFilePrinter.println("*.class");
+			dotGitIgnoreFilePrinter.println("!/alpha/test/ressources/");
+			dotGitIgnoreFilePrinter.println("*~");
+		} finally {
+			dotGitIgnoreFilePrinter.close();
+		}
+
+		// write the .git/info/exclude file
+		final File repositoryDirectory = workTree.getRepository()
+				.getDirectory();
+		final File infoDirectory = new File(repositoryDirectory, "info");
+		infoDirectory.mkdir();
+		final File infoExcludeFile = new File(infoDirectory, "exclude");
+		final PrintWriter infoExcludeFilePrinter = new PrintWriter(
+				infoExcludeFile);
+		try {
+			infoExcludeFilePrinter.println("/alpha/test/ressources/mytest.txt");
+		} finally {
+			infoExcludeFilePrinter.close();
+		}
+
+		createFile("alpha", "config.xml");
+		expectedPathes.add(createFile("alpha", "src", "Main.java"));
+		createFile("alpha", "src", "Main.class");
+		expectedPathes.add(createFile("alpha", "test", "ressources",
+				"Example.class"));
+		expectedPathes.add(createFile("alpha", "test", "ressources",
+				"input.txt"));
+		createFile("alpha", "test", "ressources", "input.txt~");
+		createFile("alpha", "test", "ressources", "mytest.txt");
+
+		final File alphaDirectory = new File(workTree.getDirectory(), "alpha");
+		final File srcDirectory = new File(alphaDirectory, "src");
+		final File testDirectory = new File(alphaDirectory, "test");
+		final File ressources = new File(testDirectory, "ressources");
+
+		expectedPathes.add(alphaDirectory);
+		expectedPathes.add(srcDirectory);
+		expectedPathes.add(testDirectory);
+		expectedPathes.add(ressources);
+
+		final List<String> patternList = new ArrayList<String>(2);
+		patternList.add("alpha");
+
+		final Iterable<File> iterable = createIterable(workTree.getDirectory(),
+				patternList);
+
+		assertIsValidIterable(iterable);
+		assertIterableReturnsSet(expectedPathes, iterable);
+	}
+
+	public void testSingleFile() throws Exception {
+		createFile("a.txt");
+		createFile("a", "a.txt");
+		createFile("a", "a", "a.txt");
+		final File expectedFile = createFile("a", "b", "a.txt");
+		createFile("a", "b", "a.c");
+
+		final String pattern = "a" + File.separator + "b" + File.separator
+				+ "a.txt";
+		final Iterable<File> iterable = createIterable(workTree.getDirectory(),
+				Arrays.asList(pattern));
+		final Set<File> expectedPathes = Collections.singleton(expectedFile);
+		assertIsValidIterable(iterable);
+		assertIterableReturnsSet(expectedPathes, iterable);
+	}
+
+	/**
+	 * Tests if the specified {@link Iterable} returns the specified set of
+	 * {@link File}s. The assertion will fail if the {@link Iterable} returns
+	 * to much, to less files. It will also fail if the {@link Iterable} returns
+	 * a file twice.
+	 * 
+	 * @param expectedContent
+	 *            the expected set of files.
+	 * @param iterable
+	 *            the {@link Iterable} to test.
+	 */
+	private void assertIterableReturnsSet(Set<File> expectedContent,
+			Iterable<File> iterable) {
+		final Set<File> returnedFiles = new HashSet<File>();
+		final List<File> doubleReturnedFiles = new ArrayList<File>();
+
+		final Iterator<File> iterator = iterable.iterator();
+		while (iterator.hasNext()) {
+			final File file = iterator.next();
+			if (!returnedFiles.add(file)) {
+				doubleReturnedFiles.add(file);
+			}
+		}
+		final Set<File> missingFiles = new HashSet<File>();
+		for (File file : expectedContent) {
+			if (!returnedFiles.contains(file)) {
+				missingFiles.add(file);
+			}
+		}
+		if (!missingFiles.isEmpty()) {
+			fail(String.format("missing pathes: %s", missingFiles));
+		}
+
+		final Set<File> unexpectedFiles = new HashSet<File>();
+		for (File file : returnedFiles) {
+			if (!expectedContent.contains(file)) {
+				unexpectedFiles.add(file);
+			}
+		}
+		if (!unexpectedFiles.isEmpty()) {
+			fail(String.format("unexpected pathes: %s", unexpectedFiles));
+		}
+
+		if (!doubleReturnedFiles.isEmpty()) {
+			fail(String.format("multiple times returned pathes: %s",
+					doubleReturnedFiles));
+		}
+
+	}
+
+	private static void assertIsValidIterable(Iterable<File> iterable) {
+		final Iterator<File> iterator = iterable.iterator();
+		while (iterator.hasNext()) {
+			iterator.next();
+		}
+		try {
+			iterator.next();
+			fail();
+		} catch (NoSuchElementException e) {
+			// expected
+		}
+	}
+
+	private File createFile(String... path) throws IOException {
+		File file = workTree.getDirectory();
+		for (int i = 0; i < path.length; i++) {
+			file = new File(file, path[i]);
+			if (i == path.length - 1) {
+				file.getParentFile().mkdirs();
+				file.createNewFile();
+				break;
+			}
+		}
+		return file;
+	}
+}
-- 
1.5.4.3

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [JGIT PATCH v3.1 16/23] Added the class LightFileTreeIterator and a test for it.
  2008-05-23 20:34 ` [JGIT PATCH v3 16/23] Added the class LightFileTreeIterator and a test for it Florian Koeberle
@ 2008-05-31 10:03   ` Florian Koeberle
  0 siblings, 0 replies; 41+ messages in thread
From: Florian Koeberle @ 2008-05-31 10:03 UTC (permalink / raw)
  To: git; +Cc: Florian Koeberle

Signed-off-by: Florian Koeberle <florianskarten@web.de>
---
 .../jgit/treewalk/LightFileTreeIteratorTest.java   |  114 ++++++++++++++++++++
 .../jgit/treewalk/LightFileTreeIterator.java       |  112 +++++++++++++++++++
 2 files changed, 226 insertions(+), 0 deletions(-)
 create mode 100644 org.spearce.jgit.test/tst/org/spearce/jgit/treewalk/LightFileTreeIteratorTest.java
 create mode 100644 org.spearce.jgit/src/org/spearce/jgit/treewalk/LightFileTreeIterator.java

diff --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
new file mode 100644
index 0000000..6febbdc
--- /dev/null
+++ b/org.spearce.jgit.test/tst/org/spearce/jgit/treewalk/LightFileTreeIteratorTest.java
@@ -0,0 +1,114 @@
+/*
+ *  Copyright (C) 2008 Florian Köberle
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public
+ *  License, version 2, as published by the Free Software Foundation.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ */
+package org.spearce.jgit.treewalk;
+
+import java.io.File;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.spearce.jgit.treewalk.rules.Rules;
+
+import junit.framework.TestCase;
+
+public class LightFileTreeIteratorTest extends TestCase {
+	private String DIRECTORY_A_NAME = "a";
+
+	private String DIRECTORY_AB_NAME = "b";
+
+	private File projectDirectory;
+
+	private File fileB;
+
+	private File directoryA;
+
+	private File directoryAB;
+
+	private File fileABA;
+
+	private File directoryAC;
+
+	private File fileACA;
+
+	private File fileACB;
+
+	@Override
+	protected void setUp() throws Exception {
+		this.projectDirectory = File.createTempFile("FileTreeIteratorTest", "");
+		projectDirectory.delete();
+		projectDirectory.mkdir();
+		projectDirectory.deleteOnExit();
+
+		this.directoryA = new File(projectDirectory, DIRECTORY_A_NAME);
+		directoryA.mkdir();
+
+		this.directoryAB = new File(directoryA, DIRECTORY_AB_NAME);
+		directoryAB.mkdir();
+
+		this.fileABA = new File(directoryAB, "a.y");
+		fileABA.createNewFile();
+
+		this.directoryAC = new File(directoryA, "c");
+		this.directoryAC.mkdir();
+
+		this.fileACA = new File(directoryAC, "a.x");
+		fileACA.createNewFile();
+
+		this.fileACB = new File(directoryAC, "b.y");
+		fileACB.createNewFile();
+
+		this.fileB = new File(projectDirectory, "b.x");
+		fileB.createNewFile();
+	}
+
+	public void testFileTreeIterator() {
+		final Iterator<File> iterator = new LightFileTreeIterator(
+				projectDirectory, Rules.IGNORE_NOTHING, false);
+		final Set<File> actualPaths = new HashSet<File>();
+		while (iterator.hasNext()) {
+			final File next = iterator.next();
+			assertFalse(actualPaths.contains(next));
+			actualPaths.add(next);
+		}
+
+		final Set<File> expectedPaths = new HashSet<File>();
+		expectedPaths.add(directoryA);
+		expectedPaths.add(fileB);
+		expectedPaths.add(directoryAB);
+		expectedPaths.add(fileABA);
+		expectedPaths.add(directoryAC);
+		expectedPaths.add(fileACA);
+		expectedPaths.add(fileACB);
+		assertEquals(expectedPaths, actualPaths);
+
+	}
+
+	public void testFileTreeIteratorWithIgnoreAllRules() {
+		final Iterator<File> iterator = new LightFileTreeIterator(
+				projectDirectory, Rules.IGNORE_ALL, false);
+		final Set<File> actualPaths = new HashSet<File>();
+		while (iterator.hasNext()) {
+			final File next = iterator.next();
+			assertFalse(actualPaths.contains(next));
+			actualPaths.add(next);
+		}
+
+		assertEquals(0, actualPaths.size());
+
+	}
+
+}
diff --git a/org.spearce.jgit/src/org/spearce/jgit/treewalk/LightFileTreeIterator.java b/org.spearce.jgit/src/org/spearce/jgit/treewalk/LightFileTreeIterator.java
new file mode 100644
index 0000000..a3822cd
--- /dev/null
+++ b/org.spearce.jgit/src/org/spearce/jgit/treewalk/LightFileTreeIterator.java
@@ -0,0 +1,112 @@
+/*
+ *  Copyright (C) 2008 Florian Köberle
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public
+ *  License, version 2, as published by the Free Software Foundation.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ */
+package org.spearce.jgit.treewalk;
+
+import java.io.File;
+import java.util.EmptyStackException;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.Stack;
+
+import org.spearce.jgit.treewalk.rules.Rules;
+
+class LightFileTreeIterator implements Iterator<File> {
+	private final Stack<File> remainingPaths;
+
+	private final Stack<Directory> remainingDirectories;
+
+	/**
+	 * Creates a new Iterator which allows to iterate over the content of the
+	 * specified rootDirectory. The rootDirectory itself is never included.
+	 * 
+	 * @param rootDirectory
+	 *            the directory tree to iterate over.
+	 * @param ignoreRules
+	 *            defines which paths are included and which aren't.
+	 * @param includeRootDirectory
+	 *            the iterator will return the rootDirectory if this is flag is
+	 *            true.
+	 */
+	LightFileTreeIterator(File rootDirectory, Rules ignoreRules,
+			boolean includeRootDirectory) {
+		remainingPaths = new Stack<File>();
+		if (includeRootDirectory) {
+			remainingPaths.add(rootDirectory);
+		}
+		remainingDirectories = new Stack<Directory>();
+		remainingDirectories.add(new Directory(rootDirectory, ignoreRules));
+	}
+
+	public boolean hasNext() {
+		findMorePathsIfNessesary();
+		return !remainingPaths.empty();
+	}
+
+	void findMorePathsIfNessesary() {
+		if (remainingPaths.isEmpty()) {
+			findMorePaths();
+		}
+	}
+
+	void findMorePaths() {
+		while (!remainingDirectories.isEmpty() && remainingPaths.isEmpty()) {
+			final Directory directory = remainingDirectories.pop();
+			final File[] paths = directory.path.listFiles();
+			for (File path : paths) {
+				final boolean fileIsDirectory = path.isDirectory();
+				if (fileIsDirectory) {
+					final Rules subDirectoryIgnoreRules = directory.ignoreRules
+							.getRulesForSubDirectory(path.getName());
+					if (subDirectoryIgnoreRules != Rules.IGNORE_ALL) {
+						final Directory subDirectory = new Directory(path,
+								subDirectoryIgnoreRules);
+						remainingDirectories.add(subDirectory);
+					}
+				}
+				if (!directory.ignoreRules.toIgnore(path.getName(),
+						fileIsDirectory)) {
+					remainingPaths.add(path);
+				}
+			}
+		}
+	}
+
+	public File next() {
+		findMorePathsIfNessesary();
+		try {
+			return remainingPaths.pop();
+		} catch (EmptyStackException e) {
+			throw new NoSuchElementException();
+		}
+	}
+
+	public void remove() {
+		throw new UnsupportedOperationException();
+	}
+
+	private class Directory {
+		final File path;
+
+		final Rules ignoreRules;
+
+		Directory(File path, Rules ignoreRules) {
+			this.path = path;
+			this.ignoreRules = ignoreRules;
+		}
+	}
+
+}
-- 
1.5.4.3

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [JGIT PATCH v3.1 23/23] Added the test class AddCommandIterationTest.
  2008-05-23 20:34 ` [JGIT PATCH v3 23/23] Added the test class AddCommandIterationTest Florian Koeberle
@ 2008-05-31 10:09   ` Florian Koeberle
  2008-06-06  0:23   ` [JGIT PATCH v3 " Robin Rosenberg
  1 sibling, 0 replies; 41+ messages in thread
From: Florian Koeberle @ 2008-05-31 10:09 UTC (permalink / raw)
  To: git; +Cc: Florian Koeberle

Signed-off-by: Florian Koeberle <florianskarten@web.de>
---
 .../treewalk/rules/AddCommandIterationTest.java    |  321 ++++++++++++++++++++
 1 files changed, 321 insertions(+), 0 deletions(-)
 create mode 100644 org.spearce.jgit.test/tst/org/spearce/jgit/treewalk/rules/AddCommandIterationTest.java

diff --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
new file mode 100644
index 0000000..9203f26
--- /dev/null
+++ b/org.spearce.jgit.test/tst/org/spearce/jgit/treewalk/rules/AddCommandIterationTest.java
@@ -0,0 +1,321 @@
+/*
+ *  Copyright (C) 2008 Florian Köberle
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public
+ *  License, version 2, as published by the Free Software Foundation.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ */
+package org.spearce.jgit.treewalk.rules;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+import org.spearce.jgit.errors.InvalidPatternException;
+import org.spearce.jgit.errors.PathNotInProjectDirectoryException;
+import org.spearce.jgit.lib.Repository;
+import org.spearce.jgit.lib.WorkTree;
+import org.spearce.jgit.treewalk.LightFileTreeIterable;
+
+public class AddCommandIterationTest extends TestCase {
+
+	private WorkTree workTree;
+
+	private AddRulesFactory factory;
+
+	private Iterable<File> createIterable(File workingDirectory,
+			List<String> filePatternsOfAddCommand)
+			throws PathNotInProjectDirectoryException, InvalidPatternException,
+			IOException {
+		final Rules rules = factory.createRules(workTree.getDirectory(),
+				workingDirectory, filePatternsOfAddCommand);
+		return new LightFileTreeIterable(workTree.getDirectory(), rules, false);
+	}
+
+	@Override
+	protected void setUp() throws Exception {
+		final File projectDirectory = File.createTempFile("test", "");
+		projectDirectory.delete();
+		projectDirectory.mkdir();
+		projectDirectory.deleteOnExit();
+		this.workTree = Repository.createWorkTree(projectDirectory);
+		this.factory = new AddRulesFactory();
+	}
+
+	public void testNoPattern() throws Exception {
+		createFile("a.txt");
+		final Iterable<File> iterable = createIterable(workTree.getDirectory(),
+				Collections.<String> emptyList());
+		final Set<File> expectedPaths = Collections.emptySet();
+		assertIsValidIterable(iterable);
+		assertIterableReturnsSet(expectedPaths, iterable);
+	}
+
+	public void testTreePattern1() throws Exception {
+		final Set<File> expectedFiles = new HashSet<File>();
+		createFile("a.txt");
+		expectedFiles.add(createFile("a", "a.txt"));
+		expectedFiles.add(createFile("a", "a", "a.txt"));
+		expectedFiles.add(createFile("a", "b", "a.txt"));
+		createFile("a", "b", "a.c");
+
+		final File directoryA = new File(workTree.getDirectory(), "a");
+
+		final Iterable<File> iterable = createIterable(directoryA, Arrays
+				.asList("*.txt"));
+		assertIsValidIterable(iterable);
+		assertIterableReturnsSet(expectedFiles, iterable);
+	}
+
+	public void testTreePattern2() throws Exception {
+		final Set<File> expectedFiles = new HashSet<File>();
+		createFile("a.txt");
+		expectedFiles.add(createFile("a", "a.txt"));
+		expectedFiles.add(createFile("a", "a", "a.txt"));
+		expectedFiles.add(createFile("a", "b", "a.txt"));
+		createFile("a", "b", "a.c");
+
+		final Iterable<File> iterable = createIterable(workTree.getDirectory(),
+				Arrays.asList("a" + File.separator + "*.txt"));
+		assertIsValidIterable(iterable);
+		assertIterableReturnsSet(expectedFiles, iterable);
+	}
+
+	public void testSelectCompleteSubdirectory() throws Exception {
+		final Set<File> expectedPaths = new HashSet<File>();
+		final File directoryA = new File(workTree.getDirectory(), "a");
+		final File directoryAA = new File(directoryA, "a");
+		final File directoryAB = new File(directoryA, "b");
+		createFile("a.txt");
+		expectedPaths.add(directoryA);
+		expectedPaths.add(directoryAA);
+		expectedPaths.add(createFile("a", "a.txt"));
+		expectedPaths.add(createFile("a", "a", "a.txt"));
+		expectedPaths.add(directoryAB);
+		expectedPaths.add(createFile("a", "b", "a.txt"));
+		expectedPaths.add(createFile("a", "b", "a.c"));
+
+		final Iterable<File> iterable = createIterable(workTree.getDirectory(),
+				Arrays.asList("a"));
+
+		assertIsValidIterable(iterable);
+		assertIterableReturnsSet(expectedPaths, iterable);
+	}
+
+	public void testSelectTwoSubdirectories() throws Exception {
+		final Set<File> expectedPaths = new HashSet<File>();
+		final File directoryA = new File(workTree.getDirectory(), "a");
+		final File directoryAA = new File(directoryA, "a");
+		final File directoryAB = new File(directoryA, "b");
+		createFile("a.txt");
+		createFile("a", "a.txt");
+		expectedPaths.add(directoryAA);
+		expectedPaths.add(createFile("a", "a", "a.txt"));
+		expectedPaths.add(directoryAB);
+		expectedPaths.add(createFile("a", "b", "a.txt"));
+		expectedPaths.add(createFile("a", "b", "a.c"));
+
+		final List<String> patternList = new ArrayList<String>(2);
+		patternList.add("a" + File.separator + "a");
+		patternList.add("a" + File.separator + "b");
+		final Iterable<File> iterable = createIterable(workTree.getDirectory(),
+				patternList);
+
+		assertIsValidIterable(iterable);
+		assertIterableReturnsSet(expectedPaths, iterable);
+	}
+
+	public void testTwoDifferentSelects() throws Exception {
+		final Set<File> expectedPaths = new HashSet<File>();
+		final File directoryA = new File(workTree.getDirectory(), "a");
+		final File directoryAA = new File(directoryA, "a");
+		createFile("a.txt");
+		createFile("a", "a.txt");
+		expectedPaths.add(directoryAA);
+		expectedPaths.add(createFile("a", "a", "a.txt"));
+		expectedPaths.add(createFile("a", "b", "a.txt"));
+		expectedPaths.add(createFile("a", "b", "c", "a.txt"));
+		createFile("a", "b", "a.c");
+
+		final List<String> patternList = new ArrayList<String>(2);
+		patternList.add("a" + File.separator + "a");
+		patternList.add("a" + File.separator + "b" + File.separator + "*.txt");
+
+		final Iterable<File> iterable = createIterable(workTree.getDirectory(),
+				patternList);
+
+		assertIsValidIterable(iterable);
+		assertIterableReturnsSet(expectedPaths, iterable);
+	}
+
+	public void testRealisticExample() throws Exception {
+		final Set<File> expectedPaths = new HashSet<File>();
+
+		// write the .gitignore file
+		final File dotGitIgnoreFile = createFile(".gitignore");
+		final PrintWriter dotGitIgnoreFilePrinter = new PrintWriter(
+				dotGitIgnoreFile);
+		try {
+			dotGitIgnoreFilePrinter.println("/alpha/config.xml");
+			dotGitIgnoreFilePrinter.println("*.class");
+			dotGitIgnoreFilePrinter.println("!/alpha/test/ressources/");
+			dotGitIgnoreFilePrinter.println("*~");
+		} finally {
+			dotGitIgnoreFilePrinter.close();
+		}
+
+		// write the .git/info/exclude file
+		final File repositoryDirectory = workTree.getRepository()
+				.getDirectory();
+		final File infoDirectory = new File(repositoryDirectory, "info");
+		infoDirectory.mkdir();
+		final File infoExcludeFile = new File(infoDirectory, "exclude");
+		final PrintWriter infoExcludeFilePrinter = new PrintWriter(
+				infoExcludeFile);
+		try {
+			infoExcludeFilePrinter.println("/alpha/test/ressources/mytest.txt");
+		} finally {
+			infoExcludeFilePrinter.close();
+		}
+
+		createFile("alpha", "config.xml");
+		expectedPaths.add(createFile("alpha", "src", "Main.java"));
+		createFile("alpha", "src", "Main.class");
+		expectedPaths.add(createFile("alpha", "test", "ressources",
+				"Example.class"));
+		expectedPaths
+				.add(createFile("alpha", "test", "ressources", "input.txt"));
+		createFile("alpha", "test", "ressources", "input.txt~");
+		createFile("alpha", "test", "ressources", "mytest.txt");
+
+		final File alphaDirectory = new File(workTree.getDirectory(), "alpha");
+		final File srcDirectory = new File(alphaDirectory, "src");
+		final File testDirectory = new File(alphaDirectory, "test");
+		final File ressources = new File(testDirectory, "ressources");
+
+		expectedPaths.add(alphaDirectory);
+		expectedPaths.add(srcDirectory);
+		expectedPaths.add(testDirectory);
+		expectedPaths.add(ressources);
+
+		final List<String> patternList = new ArrayList<String>(2);
+		patternList.add("alpha");
+
+		final Iterable<File> iterable = createIterable(workTree.getDirectory(),
+				patternList);
+
+		assertIsValidIterable(iterable);
+		assertIterableReturnsSet(expectedPaths, iterable);
+	}
+
+	public void testSingleFile() throws Exception {
+		createFile("a.txt");
+		createFile("a", "a.txt");
+		createFile("a", "a", "a.txt");
+		final File expectedFile = createFile("a", "b", "a.txt");
+		createFile("a", "b", "a.c");
+
+		final String pattern = "a" + File.separator + "b" + File.separator
+				+ "a.txt";
+		final Iterable<File> iterable = createIterable(workTree.getDirectory(),
+				Arrays.asList(pattern));
+		final Set<File> expectedPaths = Collections.singleton(expectedFile);
+		assertIsValidIterable(iterable);
+		assertIterableReturnsSet(expectedPaths, iterable);
+	}
+
+	/**
+	 * Tests if the specified {@link Iterable} returns the specified set of
+	 * {@link File}s. The assertion will fail if the {@link Iterable} returns
+	 * to much, to less files. It will also fail if the {@link Iterable} returns
+	 * a file twice.
+	 * 
+	 * @param expectedContent
+	 *            the expected set of files.
+	 * @param iterable
+	 *            the {@link Iterable} to test.
+	 */
+	private void assertIterableReturnsSet(Set<File> expectedContent,
+			Iterable<File> iterable) {
+		final Set<File> returnedFiles = new HashSet<File>();
+		final List<File> doubleReturnedFiles = new ArrayList<File>();
+
+		final Iterator<File> iterator = iterable.iterator();
+		while (iterator.hasNext()) {
+			final File file = iterator.next();
+			if (!returnedFiles.add(file)) {
+				doubleReturnedFiles.add(file);
+			}
+		}
+		final Set<File> missingFiles = new HashSet<File>();
+		for (File file : expectedContent) {
+			if (!returnedFiles.contains(file)) {
+				missingFiles.add(file);
+			}
+		}
+		if (!missingFiles.isEmpty()) {
+			fail(String.format("missing paths: %s", missingFiles));
+		}
+
+		final Set<File> unexpectedFiles = new HashSet<File>();
+		for (File file : returnedFiles) {
+			if (!expectedContent.contains(file)) {
+				unexpectedFiles.add(file);
+			}
+		}
+		if (!unexpectedFiles.isEmpty()) {
+			fail(String.format("unexpected paths: %s", unexpectedFiles));
+		}
+
+		if (!doubleReturnedFiles.isEmpty()) {
+			fail(String.format("multiple times returned paths: %s",
+					doubleReturnedFiles));
+		}
+
+	}
+
+	private static void assertIsValidIterable(Iterable<File> iterable) {
+		final Iterator<File> iterator = iterable.iterator();
+		while (iterator.hasNext()) {
+			iterator.next();
+		}
+		try {
+			iterator.next();
+			fail();
+		} catch (NoSuchElementException e) {
+			// expected
+		}
+	}
+
+	private File createFile(String... path) throws IOException {
+		File file = workTree.getDirectory();
+		for (int i = 0; i < path.length; i++) {
+			file = new File(file, path[i]);
+			if (i == path.length - 1) {
+				file.getParentFile().mkdirs();
+				file.createNewFile();
+				break;
+			}
+		}
+		return file;
+	}
+}
-- 
1.5.4.3

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* Re: [JGIT PATCH v3 0/23] Implementation of a file tree iteration using ignore rules.
  2008-05-23 20:34 [JGIT PATCH v3 0/23] Implementation of a file tree iteration using ignore rules Florian Koeberle
                   ` (22 preceding siblings ...)
  2008-05-23 20:34 ` [JGIT PATCH v3 23/23] Added the test class AddCommandIterationTest Florian Koeberle
@ 2008-05-31 10:17 ` Florian Köberle
  2008-06-06  0:22 ` Robin Rosenberg
  2008-06-07  8:43 ` Shawn O. Pearce
  25 siblings, 0 replies; 41+ messages in thread
From: Florian Köberle @ 2008-05-31 10:17 UTC (permalink / raw)
  To: git

Hi

In send in two updated versions of two patches. I renamed "pathes" to 
"paths".

Thanks Paolo for telling me about this.

Best regards,
Florian Koeberle

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [JGIT PATCH v3 0/23] Implementation of a file tree iteration using ignore rules.
  2008-05-23 20:34 [JGIT PATCH v3 0/23] Implementation of a file tree iteration using ignore rules Florian Koeberle
                   ` (23 preceding siblings ...)
  2008-05-31 10:17 ` [JGIT PATCH v3 0/23] Implementation of a file tree iteration using ignore rules Florian Köberle
@ 2008-06-06  0:22 ` Robin Rosenberg
  2008-06-08 16:37   ` Florian Köberle
  2008-06-07  8:43 ` Shawn O. Pearce
  25 siblings, 1 reply; 41+ messages in thread
From: Robin Rosenberg @ 2008-06-06  0:22 UTC (permalink / raw)
  To: Florian Koeberle; +Cc: git

fredagen den 23 maj 2008 22.34.09 skrev Florian Koeberle:
> 
> Hi
> 
> This patch set contains a new fnmatch implementation.

Looks ok, with me. Only minor comments in separate mail.

> Unsupported are colon expressions like ":alpha:". I didn't expect git-add to support it, but as I just noticed git does.
Maybe we should anticipate it and throw an exception if one tries the pattern and not treat it as [alph:] .

Well we noted they were broken in Git so (separate thread) so we may as well try something sane. 

-- robin

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [JGIT PATCH v3 05/23] Added the iterface Rules.
  2008-05-23 20:34 ` [JGIT PATCH v3 05/23] Added the iterface Rules Florian Koeberle
@ 2008-06-06  0:22   ` Robin Rosenberg
  0 siblings, 0 replies; 41+ messages in thread
From: Robin Rosenberg @ 2008-06-06  0:22 UTC (permalink / raw)
  To: Florian Koeberle; +Cc: git


s/Iterface/Interface/

fredagen den 23 maj 2008 22.34.14 skrev Florian Koeberle:
> Signed-off-by: Florian Koeberle <florianskarten@web.de>
> ---
>  .../src/org/spearce/jgit/treewalk/rules/Rules.java |   99 ++++++++++++++++++++
>  1 files changed, 99 insertions(+), 0 deletions(-)
>  create mode 100644 org.spearce.jgit/src/org/spearce/jgit/treewalk/rules/Rules.java
> 
> diff --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
> +	public abstract boolean toIgnore(String fileName, boolean fileIsDirectory);

Shouldn't this be shouldIgnore instead? toXXXX is a name of a converter as e.g. toString

> +		@Override
> +		public String toString() {
> +			return "ignore all rules";
Probably better with something like "Rules[IGNOREALL]" to distinguish it
from other strings. The bracketed toString is common for method intended
for debugging.

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [JGIT PATCH v3 06/23] Added the class FileNamePattern.
  2008-05-23 20:34 ` [JGIT PATCH v3 06/23] Added the class FileNamePattern Florian Koeberle
@ 2008-06-06  0:22   ` Robin Rosenberg
  0 siblings, 0 replies; 41+ messages in thread
From: Robin Rosenberg @ 2008-06-06  0:22 UTC (permalink / raw)
  To: Florian Koeberle; +Cc: git

> +	public boolean match(String fileName, boolean fileIsDirectory) {
> +		if (matchDirectoriesOnly && !fileIsDirectory) {
> +			return false;
> +		}
> +		fileNameMatcher.resetStringToMatch();

Partially discusses before, but here is another aspect. One advantage
with bracketless code is that you get an extra blank line for free.

	if (matchDirectoriesOnly && !fileIsDirectory)
		return false;

	fileNameMatcher.resetStringToMatch();

-- robin

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [JGIT PATCH v3 09/23] Added a Rules interface implementation and a factory for it.
  2008-05-23 20:34 ` [JGIT PATCH v3 09/23] Added a Rules interface implementation and a factory for it Florian Koeberle
@ 2008-06-06  0:23   ` Robin Rosenberg
  0 siblings, 0 replies; 41+ messages in thread
From: Robin Rosenberg @ 2008-06-06  0:23 UTC (permalink / raw)
  To: Florian Koeberle; +Cc: git

fredagen den 23 maj 2008 22.34.18 skrev Florian Koeberle:
> +	/**
> +	 * @see Rules#toIgnore(java.lang.String, boolean)
> +	 */
> +	public boolean toIgnore(String fileName, boolean fileIsDirectory) {

(Applies to many places)
Don't make javadoc style comments for overrides. Rather just omit it
or use a plain comment. Also use the @Override annotation if you
override an implementation. We use Java 5, so we may as well use
all bells and whistles that make sense.

I'm not sure about other IDE's, but Eclipse will automaticall picks up then
javadoc for the superclass or interface that declare the methos being 
overridden if the overriding method does not hava a javadoc comment.
The javadoc tool also does this so I assume any descent IDE
does too (if not it's a bug).

-- robin

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [JGIT PATCH v3 19/23] Added WorkTree class which can be constructed over Repository.
  2008-05-23 20:34 ` [JGIT PATCH v3 19/23] Added WorkTree class which can be constructed over Repository Florian Koeberle
@ 2008-06-06  0:23   ` Robin Rosenberg
  0 siblings, 0 replies; 41+ messages in thread
From: Robin Rosenberg @ 2008-06-06  0:23 UTC (permalink / raw)
  To: Florian Koeberle; +Cc: git

fredagen den 23 maj 2008 22.34.28 skrev Florian Koeberle:
> ---
>  .../src/org/spearce/jgit/lib/Repository.java       |   57 +++++++++++++++++
>  .../src/org/spearce/jgit/lib/WorkTree.java         |   67 ++++++++++++++++++++
>  2 files changed, 124 insertions(+), 0 deletions(-)
>  create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/WorkTree.java
> 
> diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
> +	public Commit setupHEADRef(final String remoteBranch, final String branch)
> +			throws IOException {
> +		Commit mapCommit = mapCommit(remoteBranch);
> +		String refName = Constants.HEADS_PREFIX + "/" + branch;
> +		LockFile masterRef = lockRef(refName);
> +		try {
> +			masterRef.write(mapCommit.getCommitId());
> +			masterRef.commit();
> +		} finally {
> +			masterRef.unlock();
> +		}
> +		writeSymref(Constants.HEAD, refName);
> +		return mapCommit;
> +	}
Shouldn't someone be calling this?

> diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/WorkTree.java b/org.spearce.jgit/src/org/spearce/jgit/lib/WorkTree.java
> +	/**
> +	 * Closes the git repository of this project.
> +	 */
> +	public void closeRepository() {
> +		repository.close();
> +	}

This is redundant. Very few callers need it and those can just as well
call getRepsitory().close() anyway.

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [JGIT PATCH v3 20/23] Added the class NoGitRepositoryFoundException.
  2008-05-23 20:34 ` [JGIT PATCH v3 20/23] Added the class NoGitRepositoryFoundException Florian Koeberle
@ 2008-06-06  0:23   ` Robin Rosenberg
  2008-06-08 16:14     ` Florian Köberle
  0 siblings, 1 reply; 41+ messages in thread
From: Robin Rosenberg @ 2008-06-06  0:23 UTC (permalink / raw)
  To: Florian Koeberle; +Cc: git

fredagen den 23 maj 2008 22.34.29 skrev Florian Koeberle:
> +	public NoGitRepositoryFoundException(final File fileWeSearchedRepositoryFor) {
> +		super(String.format("No repository found for file '%s'",
> +				fileWeSearchedRepositoryFor));

This is any odd patterrn. Usually we use + to concatenate strimgs.

-- robin

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [JGIT PATCH v3 21/23] Formatted Repository class.
  2008-05-23 20:34 ` [JGIT PATCH v3 21/23] Formatted Repository class Florian Koeberle
@ 2008-06-06  0:23   ` Robin Rosenberg
  0 siblings, 0 replies; 41+ messages in thread
From: Robin Rosenberg @ 2008-06-06  0:23 UTC (permalink / raw)
  To: Florian Koeberle; +Cc: git

I'm slightly allergic to formatting patches.

-- robin

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [JGIT PATCH v3 23/23] Added the test class AddCommandIterationTest.
  2008-05-23 20:34 ` [JGIT PATCH v3 23/23] Added the test class AddCommandIterationTest Florian Koeberle
  2008-05-31 10:09   ` [JGIT PATCH v3.1 " Florian Koeberle
@ 2008-06-06  0:23   ` Robin Rosenberg
  1 sibling, 0 replies; 41+ messages in thread
From: Robin Rosenberg @ 2008-06-06  0:23 UTC (permalink / raw)
  To: Florian Koeberle; +Cc: git

> diff --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
> +	@Override
> +	protected void setUp() throws Exception {
> +		final File projectDirectory = File.createTempFile("test", "");
> +		projectDirectory.delete();
> +		projectDirectory.mkdir();
> +		projectDirectory.deleteOnExit();
> +		this.workTree = Repository.createWorkTree(projectDirectory);
> +		this.factory = new AddRulesFactory();
> +	}

I've had some problems with this pattern, especially on Windows. We need
some support class, like the RepositoryTestCase to handle the not so nice
parts of getting tests to run, rerun and cleam up after themselves. Eclipse
sometims adds an extra twist becuase File may be lefte open between test
runs, which is the reason RepositoryTestCase uses a new directories every time.

Does this work at all? delete() requires directories to be empty in order to delete.

-- robin

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [JGIT PATCH v3 0/23] Implementation of a file tree iteration using ignore rules.
  2008-05-23 20:34 [JGIT PATCH v3 0/23] Implementation of a file tree iteration using ignore rules Florian Koeberle
                   ` (24 preceding siblings ...)
  2008-06-06  0:22 ` Robin Rosenberg
@ 2008-06-07  8:43 ` Shawn O. Pearce
  25 siblings, 0 replies; 41+ messages in thread
From: Shawn O. Pearce @ 2008-06-07  8:43 UTC (permalink / raw)
  To: Florian Koeberle; +Cc: git, Robin Rosenberg

Florian Koeberle <florianskarten@web.de> wrote:
>  .../org/spearce/jgit/lib/FileNameMatcherTest.java  |  311 +++++++++++++
>  .../jgit/treewalk/LightFileTreeIteratorTest.java   |  114 +++++
>  .../treewalk/rules/AddCommandIterationTest.java    |  321 +++++++++++++
>  .../treewalk/rules/OverallIgnoreRulesTest.java     |  375 +++++++++++++++
>  .../jgit/errors/InvalidPatternException.java       |   44 ++
>  .../jgit/errors/NoGitRepositoryFoundException.java |   28 ++
>  .../errors/PathNotInProjectDirectoryException.java |   25 +
>  .../src/org/spearce/jgit/lib/Constants.java        |   30 +-
>  .../src/org/spearce/jgit/lib/FileNameMatcher.java  |  376 +++++++++++++++
>  .../src/org/spearce/jgit/lib/Repository.java       |  482 +++++++++++++-------
>  .../src/org/spearce/jgit/lib/WorkTree.java         |   67 +++
>  .../jgit/treewalk/LightFileTreeIterable.java       |   59 +++
>  .../jgit/treewalk/LightFileTreeIterator.java       |  112 +++++
>  .../jgit/treewalk/rules/AddRuleListFactory.java    |   75 +++
>  .../jgit/treewalk/rules/AddRulesFactory.java       |   90 ++++
>  .../jgit/treewalk/rules/FileNamePattern.java       |   58 +++
>  .../jgit/treewalk/rules/FilePathPattern.java       |   76 +++
>  .../spearce/jgit/treewalk/rules/FilePattern.java   |  107 +++++
>  .../jgit/treewalk/rules/IgnoreRuleListFactory.java |   94 ++++
>  .../src/org/spearce/jgit/treewalk/rules/Rule.java  |   61 +++
>  .../treewalk/rules/RuleListToObjectConverter.java  |  130 ++++++
>  .../src/org/spearce/jgit/treewalk/rules/Rules.java |   99 ++++
>  .../jgit/treewalk/rules/RulesImplementation.java   |   73 +++

I finally found time while travelling around on planes this past
week to review this series.  Since I didn't have access to my email
client I didn't organize my thoughts per-patch very well, if it all.

I agree with all of Robin's comments.  He noticed a few things I
didn't, but they all made sense once I read them.

Without further ado, here are my remarks on this current series:

----
Please consider using a cleanup commit to:

- Rename FileNameMatcher.extendStringToMatch to just append().
  The action used here is generally called "append" in Java, see
  StringBuffer for example.

- Rename FileNameMatcher.resetStringToMatch to just reset().  It
  is cleaning up the state and the only state it can cleanup is
  the string we are matching against.

- Rename FileNameMatcher.willExtendResultInNoMatch() to say
  canAppendMatch() with the negation in the callers of the
  current willExtendResultInNoMatch() method.  I think its
  easier to read as "!canAppendMatch()".

Ecipse can easily handle the refactoring and its probably easier
to just do at the end of the series rather than fixing every commit
along the way.

----
I'm not sure I see why we have FilePattern.isSameForSubdirectories(),
or Rule.isSameForSubDirectories().  By the end of the series you do
not call either method.  These should be removed from the abstract
definition and from all implementing classes.  Again a cleanup commit
to remove this would be OK.

----
Class Rule should not be public; none of its members are public.

FileNameMatcher's Head.getNextHeads and AbstractHead.setNewHeads
should not be public either; the interfaces are visible only to
this package.

In general please make method access reflect the access of the
class the method is declared within.  If the class is not a public
class then the method isn't visible, even if it is marked public,
so instead mark it package-level.

----
Since FilePattern is not public none of its members should be public;
use default package access for the MATCH_ALWAYS and MATCH_NEVER
constants and private access for the static inner classes that
supply those two implementations.

----
In FileNameMatcher the symbol name invalidWildgetCharacter is used as
a parameter to a number of methods/constructors.  Its name does not
mean anything to me as I don't know what "Wildget" means.  In many
cases this long name is causing Eclipse to wrap the code poorly.
Rename it to notInWild perhaps?

In FileNameMatcher.extendStringToMatchByOneCharacter you don't need
to use an int index into the List<Head> called "heads".  Instead
use the Java 5 syntax of "for (final Head head : heads)" and let
the compiler generate the loop.  If the memory allocation of the
Iterator is too costly here then you probably need to rethink your
storage anyway.  You could have getNextHeads return you an Head[]
instead of List<Head>.  The compiler can loop over the array and
an array takes up less memory than an ArrayList of the same size.

In FileNameMatcher.extractGroupPatternWithoutBrackets your string
literals for the pattern argument of String.format() are way too
long and cause them to overflow the line.  Break the string into
multiple literals and use + to append them together.  Any decent
Java compiler will combine them back into a single string in the
class string pool.  Even if the compiler sucks, this is for an
error condition only.  Who cares how long the StringBuilder is
going to take at that point, the operation has failed.

----
Don't create a local variable just to return it.  You do this
at least in FileNameMatcher.extractGroupPatternWithoutBrackets:

	final String groupPatternWithOutBrackets = patternString.substring(
		start + 1, closingBracketIndex);
	return groupPatternWithOutBrackets;

and it looks more complex than is really needed here:

	return patternString.substring(start + 1, closingBracketIndex);

This is also true in createMatcherForSuffix.  You can reduce
that entire method to just:

	return new FileNameMatcher(new ArrayList<Head>(heads));

which is much easier to read than the 3 lines you have to
create the copyOfHeads.

----
Please use a for loop where it makes sense.  In the case of
FileNameMatcher.extractGroupPatternWithoutBrackets you use a
while loop with a variable called "start", with a post condition
to decrement the variable.  That's why we have the for(;;) loop
construct in the language.

But this entire method is 30 lines of code to say this:

	final int ob = pattern.lastIndexOf('[', closingBracket - 1);
	final int cb = pattern.lastIndexOf(']', closingBracket - 1);
	if (ob < 0 || cb > ob)
		throw new InvalidPatternException("Unbalanced []", pattern);
	return pattern.substring(ob + 1, closingBracket);

----
In FileNameMatcher the isMatch method is _way_ more complex than
it needs to be.  Just use:

	public boolean isMatch() {
		return heads.contains(LastHead.INSTANCE);
	}

contains works perfectly well.  From what I can tell of the
implementation the size of heads should be fairly small, usually
only 1 or 2 items at most.  Testing via contains without using a
backward traversing ListIterator is just fine here.

----
Please don't initialize fields to null.  For example in the
AbstractHead class of FileNameMatcher you set newHeads = null;
the JVM does this for you automatically and that makes your
own statement redundant.

----
I'm not sure I see the value in the Head interface within
FileNameMatcher.  Only two implementations exist; the one for
AbstractHead and the one for LastHead.  Since LastHead is already
just a singleton you might as well just have it extend from the
AbstractHead base class and "waste" the couple of words of static
memory for an empty head list.

----
In FilePathPattern you use "new Character('/')".  Instead use the
flyweight one that comes with the JRE by "Character.valueOf('/')".

----
In general the implementation still feels overly complex to me.
Lots of interfaces, factories and delegation for what should be a
relatively simple thing of pruning names that should be skipped.

It also seems to be somewhat special cased around git-add sort
of behavior.  We also need to process ignore lists for merge, to
make sure we can safely overwrite something or not if there is an
untracked file in the working tree that conflicts with what we are
merging the working directory to.

-- 
Shawn.

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [JGIT PATCH v3 20/23] Added the class NoGitRepositoryFoundException.
  2008-06-06  0:23   ` Robin Rosenberg
@ 2008-06-08 16:14     ` Florian Köberle
  2008-06-08 21:05       ` Robin Rosenberg
  0 siblings, 1 reply; 41+ messages in thread
From: Florian Köberle @ 2008-06-08 16:14 UTC (permalink / raw)
  To: Robin Rosenberg; +Cc: git

Robin Rosenberg wrote:
 >> +		super(String.format("No repository found for file '%s'",
 >> +				fileWeSearchedRepositoryFor));
 >
 > This is any odd patterrn. Usually we use + to concatenate strimgs.

Hi Robin,

I know two good reason why you should use formating functions over 
string concatenation via the plus sign:

1.) formated strings are better translatable. e.g.
"The string '%s' is more then %s characters long"
is easier to translate then the three strings:
"The string '"
"' is more then "
" characters long"

2.) Whitespace mistakes are easier to see. e.g.
(i + "coins") and ("%scoins", i)

Sure you can make the mistake to provide not enough arguments, but 
that's not so worse:
a.) Some IDEs, like Intellij IDEA warn you if you call a formating 
function with to few arguments.
b.) A exception will be thrown at the time the function is called, if 
there are not enough arguments. Thus you will notice your mistake very soon.

Best regards,
Florian

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [JGIT PATCH v3 0/23] Implementation of a file tree iteration using ignore rules.
  2008-06-06  0:22 ` Robin Rosenberg
@ 2008-06-08 16:37   ` Florian Köberle
  2008-06-08 21:28     ` Robin Rosenberg
  0 siblings, 1 reply; 41+ messages in thread
From: Florian Köberle @ 2008-06-08 16:37 UTC (permalink / raw)
  To: Robin Rosenberg; +Cc: git

>> Unsupported are colon expressions like ":alpha:". I didn't expect git-add to support it, but as I just noticed git does.
> Maybe we should anticipate it and throw an exception if one tries the pattern and not treat it as [alph:] .
> 
> Well we noted they were broken in Git so (separate thread) so we may as well try something sane. 
Just did some tests and noted that the shell and git does not support 
them. I guess I thought that they work because [:alpha:] matched "a".

Hi Robin

The bash shell doesn't support [:alpha:] too:
$ mkdir test
$ cd test
$ touch a
$ touch b
$ touch :
$ ls [:alpha:]
:  a

The fnmatch function of the python module fnmatch 
(http://docs.python.org/lib/module-fnmatch.html) does not support 
:alpha: too.

example:
$python
 >>> from fnmatch import fnmatch
 >>> fnmatch("a","[:alpha:]")
False

So I see no reason for displaying a warning.

Best regards,
Florian

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [JGIT PATCH v3 20/23] Added the class NoGitRepositoryFoundException.
  2008-06-08 16:14     ` Florian Köberle
@ 2008-06-08 21:05       ` Robin Rosenberg
  0 siblings, 0 replies; 41+ messages in thread
From: Robin Rosenberg @ 2008-06-08 21:05 UTC (permalink / raw)
  To: Florian Köberle; +Cc: git

söndagen den 8 juni 2008 18.14.00 skrev Florian Köberle:
> Robin Rosenberg wrote:
>  >> +		super(String.format("No repository found for file '%s'",
>  >> +				fileWeSearchedRepositoryFor));
>  >
>  > This is any odd patterrn. Usually we use + to concatenate strimgs.
> 
> Hi Robin,
> 
> I know two good reason why you should use formating functions over 
> string concatenation via the plus sign:
> 
> 1.) formated strings are better translatable. e.g.
> "The string '%s' is more then %s characters long"
[..]
> 2.) Whitespace mistakes are easier to see. e.g.
> (i + "coins") and ("%scoins", i)
> 
> Sure you can make the mistake to provide not enough arguments, but 
> that's not so worse:
> a.) Some IDEs, like Intellij IDEA warn you if you call a formating 
> function with to few arguments.

I'm so ashamed... I used to like printf in C, but I've hardly used it in Java. I
probably will use it more now. Seems Eclipse doesn't check (even GCC
does that).

-- robin

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [JGIT PATCH v3 0/23] Implementation of a file tree iteration using ignore rules.
  2008-06-08 16:37   ` Florian Köberle
@ 2008-06-08 21:28     ` Robin Rosenberg
  2008-06-09 17:11       ` Florian Köberle
  0 siblings, 1 reply; 41+ messages in thread
From: Robin Rosenberg @ 2008-06-08 21:28 UTC (permalink / raw)
  To: Florian Köberle; +Cc: git

söndagen den 8 juni 2008 18.37.30 skrev Florian Köberle:
(please retatain who said what)
> >> Unsupported are colon expressions like ":alpha:". I didn't expect git-add to support it, but as I just noticed git does.
> > Maybe we should anticipate it and throw an exception if one tries the pattern and not treat it as [alph:] .
> > 
> > Well we noted they were broken in Git so (separate thread) so we may as well try something sane. 
> Just did some tests and noted that the shell and git does not support 
> them. I guess I thought that they work because [:alpha:] matched "a".
> 
> Hi Robin
> 
> The bash shell doesn't support [:alpha:] too:
> $ mkdir test
> $ cd test
> $ touch a
> $ touch b
> $ touch :
> $ ls [:alpha:]
> :  a
Oh, it does. [:alpha:] is a character class, like a-z. So you use [[:alpha:]], which is what git as well as bash
understands.

> The fnmatch function of the python module fnmatch 
> (http://docs.python.org/lib/module-fnmatch.html) does not support 
> :alpha: too.
> 
> example:
> $python
>  >>> from fnmatch import fnmatch
>  >>> fnmatch("a","[:alpha:]")
> False
Hmm. Odd:

$ python
Python 2.5.2 (r252:60911, Apr 12 2008, 01:47:55)
[GCC 4.2.3 (4.2.3-6mnb1)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from fnmatch import fnmatch
>>> fnmatch("a","[:alpha:]")
True

But then, it's matching the a(s), not the character class.

>>> fnmatch("x","[:alpha:]")
False
>>> fnmatch("x","[[:alpha:]]")
False

-- robin

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [JGIT PATCH v3 0/23] Implementation of a file tree iteration using ignore rules.
  2008-06-08 21:28     ` Robin Rosenberg
@ 2008-06-09 17:11       ` Florian Köberle
  0 siblings, 0 replies; 41+ messages in thread
From: Florian Köberle @ 2008-06-09 17:11 UTC (permalink / raw)
  To: Robin Rosenberg; +Cc: git

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Robin Rosenberg wrote:
| Oh, it does. [:alpha:] is a character class, like a-z. So you use
[[:alpha:]], which is what git as well as bash
| understands.
Naturally I will then implement the POSIX character classes as listed at
(http://en.wikipedia.org/wiki/Regular_expression#POSIX_character_classes)
for FileNameMatcher too.


|
|> The fnmatch function of the python module fnmatch
|> (http://docs.python.org/lib/module-fnmatch.html) does not support
|> :alpha: too.
|>
|> example:
|> $python
|>  >>> from fnmatch import fnmatch
|>  >>> fnmatch("a","[:alpha:]")
|> False
| Hmm. Odd:
[...]
|>>> fnmatch("a","[:alpha:]")
| True
Oops.. of course the output was True for me too, but for
fnmatch("b","[:alpha:]") it wasn't.

Best Regards,
Florian Köberle
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFITWRC59ca4mzhfxMRAjdrAJ9/6VDQOOHdm0WGP/W+l84LiKrOhQCfdkJn
DEcnz0WTzockGJ+w9S1/4xk=
=/PpE
-----END PGP SIGNATURE-----

^ permalink raw reply	[flat|nested] 41+ messages in thread

end of thread, other threads:[~2008-06-09 17:12 UTC | newest]

Thread overview: 41+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-05-23 20:34 [JGIT PATCH v3 0/23] Implementation of a file tree iteration using ignore rules Florian Koeberle
2008-05-23 20:34 ` [JGIT PATCH v3 01/23] Added the class InvalidPatternException Florian Koeberle
2008-05-23 20:34 ` [JGIT PATCH v3 02/23] Added the class FileNameMatcher and a test class for it Florian Koeberle
2008-05-23 20:34 ` [JGIT PATCH v3 03/23] Added the interface FilePattern Florian Koeberle
2008-05-23 20:34 ` [JGIT PATCH v3 04/23] Added the class Rule Florian Koeberle
2008-05-23 20:34 ` [JGIT PATCH v3 05/23] Added the iterface Rules Florian Koeberle
2008-06-06  0:22   ` Robin Rosenberg
2008-05-23 20:34 ` [JGIT PATCH v3 06/23] Added the class FileNamePattern Florian Koeberle
2008-06-06  0:22   ` Robin Rosenberg
2008-05-23 20:34 ` [JGIT PATCH v3 07/23] Added the class FilePathPattern Florian Koeberle
2008-05-23 20:34 ` [JGIT PATCH v3 08/23] Added the class IgnoreRuleListFactory Florian Koeberle
2008-05-23 20:34 ` [JGIT PATCH v3 09/23] Added a Rules interface implementation and a factory for it Florian Koeberle
2008-06-06  0:23   ` Robin Rosenberg
2008-05-23 20:34 ` [JGIT PATCH v3 10/23] Added test class OverallIgnoreRulestest Florian Koeberle
2008-05-23 20:34 ` [JGIT PATCH v3 11/23] Added the class PathNotInProjectDirectoryException Florian Koeberle
2008-05-23 20:34 ` [JGIT PATCH v3 12/23] Added the class AddRuleListFactory Florian Koeberle
2008-05-23 20:34 ` [JGIT PATCH v3 13/23] Formatted Constants class Florian Koeberle
2008-05-23 20:34 ` [JGIT PATCH v3 14/23] Added constant REPOSITORY_DIRECTORY_NAME to " Florian Koeberle
2008-05-23 20:34 ` [JGIT PATCH v3 15/23] Added class AddRulesFactory Florian Koeberle
2008-05-23 20:34 ` [JGIT PATCH v3 16/23] Added the class LightFileTreeIterator and a test for it Florian Koeberle
2008-05-31 10:03   ` [JGIT PATCH v3.1 " Florian Koeberle
2008-05-23 20:34 ` [JGIT PATCH v3 17/23] Added class LightFileTreeIterable Florian Koeberle
2008-05-23 20:34 ` [JGIT PATCH v3 18/23] Added path related constants to the Constants class Florian Koeberle
2008-05-23 20:34 ` [JGIT PATCH v3 19/23] Added WorkTree class which can be constructed over Repository Florian Koeberle
2008-06-06  0:23   ` Robin Rosenberg
2008-05-23 20:34 ` [JGIT PATCH v3 20/23] Added the class NoGitRepositoryFoundException Florian Koeberle
2008-06-06  0:23   ` Robin Rosenberg
2008-06-08 16:14     ` Florian Köberle
2008-06-08 21:05       ` Robin Rosenberg
2008-05-23 20:34 ` [JGIT PATCH v3 21/23] Formatted Repository class Florian Koeberle
2008-06-06  0:23   ` Robin Rosenberg
2008-05-23 20:34 ` [JGIT PATCH v3 22/23] Added findWorkTree method to " Florian Koeberle
2008-05-23 20:34 ` [JGIT PATCH v3 23/23] Added the test class AddCommandIterationTest Florian Koeberle
2008-05-31 10:09   ` [JGIT PATCH v3.1 " Florian Koeberle
2008-06-06  0:23   ` [JGIT PATCH v3 " Robin Rosenberg
2008-05-31 10:17 ` [JGIT PATCH v3 0/23] Implementation of a file tree iteration using ignore rules Florian Köberle
2008-06-06  0:22 ` Robin Rosenberg
2008-06-08 16:37   ` Florian Köberle
2008-06-08 21:28     ` Robin Rosenberg
2008-06-09 17:11       ` Florian Köberle
2008-06-07  8:43 ` Shawn O. Pearce

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).