git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[JGIT PATCH v3 09/23] Added a Rules interface implementation and a factory for it.

From
FKFlorian Koeberle <florianskarten@web.de>
Date
May 23, 2008, 20:34 UTC
Message-ID
<1211574872-23676-10-git-send-email-florianskarten@web.de>
In-Reply-To
<1211574872-23676-1-git-send-email-florianskarten@web.de>
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
Previous: Florian KoeberleNext: Robin Rosenberg
Message 12 of 41 in “Implementation of a file tree iteration using ignore rules.”
  1. 0/23 Implementation of a file tree iteration using ignore rules.Florian Koeberle, May 23, 2008
  2. 01/23 Added the class InvalidPatternException.Florian Koeberle, May 23, 2008
  3. 02/23 Added the class FileNameMatcher and a test class for it.Florian Koeberle, May 23, 2008
  4. 03/23 Added the interface FilePattern.Florian Koeberle, May 23, 2008
  5. 04/23 Added the class Rule.Florian Koeberle, May 23, 2008
  6. 05/23 Added the iterface Rules.Florian Koeberle, May 23, 2008
  7. Robin RosenbergJun 6, 2008
  8. 06/23 Added the class FileNamePattern.Florian Koeberle, May 23, 2008
  9. Robin RosenbergJun 6, 2008
  10. 07/23 Added the class FilePathPattern.Florian Koeberle, May 23, 2008
  11. 08/23 Added the class IgnoreRuleListFactory.Florian Koeberle, May 23, 2008
  12. 09/23 Added a Rules interface implementation and a factory for it.Florian Koeberle, May 23, 2008
  13. Robin RosenbergJun 6, 2008
  14. 10/23 Added test class OverallIgnoreRulestest.Florian Koeberle, May 23, 2008
  15. 11/23 Added the class PathNotInProjectDirectoryException.Florian Koeberle, May 23, 2008
  16. 12/23 Added the class AddRuleListFactory.Florian Koeberle, May 23, 2008
  17. 13/23 Formatted Constants class.Florian Koeberle, May 23, 2008
  18. 14/23 Added constant REPOSITORY_DIRECTORY_NAME to Constants class.Florian Koeberle, May 23, 2008
  19. 15/23 Added class AddRulesFactory.Florian Koeberle, May 23, 2008
  20. 16/23 Added the class LightFileTreeIterator and a test for it.Florian Koeberle, May 23, 2008
  21. 16/23 Added the class LightFileTreeIterator and a test for it.Florian Koeberle, May 31, 2008
  22. 17/23 Added class LightFileTreeIterable.Florian Koeberle, May 23, 2008
  23. 18/23 Added path related constants to the Constants class.Florian Koeberle, May 23, 2008
  24. 19/23 Added WorkTree class which can be constructed over Repository.Florian Koeberle, May 23, 2008
  25. Robin RosenbergJun 6, 2008
  26. 20/23 Added the class NoGitRepositoryFoundException.Florian Koeberle, May 23, 2008
  27. Robin RosenbergJun 6, 2008
  28. Florian KöberleJun 8, 2008
  29. Robin RosenbergJun 8, 2008
  30. 21/23 Formatted Repository class.Florian Koeberle, May 23, 2008
  31. Robin RosenbergJun 6, 2008
  32. 22/23 Added findWorkTree method to Repository class.Florian Koeberle, May 23, 2008
  33. 23/23 Added the test class AddCommandIterationTest.Florian Koeberle, May 23, 2008
  34. 23/23 Added the test class AddCommandIterationTest.Florian Koeberle, May 31, 2008
  35. Robin RosenbergJun 6, 2008
  36. Florian KöberleMay 31, 2008
  37. Robin RosenbergJun 6, 2008
  38. Florian KöberleJun 8, 2008
  39. Robin RosenbergJun 8, 2008
  40. Florian KöberleJun 9, 2008
  41. Shawn O. PearceJun 7, 2008

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.