{"thread":{"id":"13461","subject":"[JGIT PATCH 0/m] Implementation of a file tree iteration using ignore rules.","startedAt":"2008-05-10T13:00:18Z","lastAt":"2008-05-11T00:16:12Z","messageCount":35,"participants":["Florian Koeberle","Robin Rosenberg","Shawn O. Pearce"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"76507","messageId":"1210424440-13886-1-git-send-email-florianskarten@web.de","threadId":"13461","inReplyTo":null,"subject":"[JGIT PATCH 0/m] Implementation of a file tree iteration using ignore rules.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-05-10T13:00:18Z","receivedAt":"2008-05-10T13:00:18Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Hi\n\nhere are the patches.\n\nThe implementation does a lot of performance optimizations:\n\n1.) Instead of checking all the rules from top to bottom, I simply take the first matching rule beginning from bottom. I actually have intern a list with a inversed order and take then the first matching rule.\n\n\n2.) Each sub directory has it's own optimized rules.\n\n2.1.) Rules which can never match are removed. e.g. There is no need to check the rule \"/a\" in the directory b.\n\n2.2.) 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\".\n\n2.3.) 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\",\n\n2.4.) \"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.\n\n2.5.) When converting the rule list into an instance of the Rules interface, rule lists with only one always matching rule are converted to Rules.IGNORE_NOTHING and Rules.IGNORE_ALL objects. These special objects avoid unessary object construction as they reuse themself for sub directories.\n\n\n3.) Only rules are evaluated which could match at the current directory level. e.g. You don't need to check the rule /a/b/c for every file in /a, but only for files in the directory /a/b\n\n\n4.) The Iterator doesn't walk into trees from which it knows that they will never match. It can do so by comparing the rules instance for the directory with the value of Rules.IGNORE_ALL.\n\nBest regards,\nFlorian Koeberle\n"},{"id":"76512","messageId":"1210424440-13886-2-git-send-email-florianskarten@web.de","threadId":"13461","inReplyTo":"1210424440-13886-1-git-send-email-florianskarten@web.de","subject":"[JGIT PATCH 01/22] Start of an implementation of a git like command line tool.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-05-10T13:00:19Z","receivedAt":"2008-05-10T13:00:19Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Only the \"help\" command is currenly supported, but it is extendable.\n\nSigned-off-by: Florian Koeberle <florianskarten@web.de>\n---\n .../src/org/spearce/jgit/pgm/Command.java          |   40 +++++++\n .../src/org/spearce/jgit/pgm/MainProgram.java      |  114 ++++++++++++++++++++\n 2 files changed, 154 insertions(+), 0 deletions(-)\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/pgm/Command.java\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/pgm/MainProgram.java\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/pgm/Command.java b/org.spearce.jgit/src/org/spearce/jgit/pgm/Command.java\nnew file mode 100644\nindex 0000000..cf66b20\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/pgm/Command.java\n@@ -0,0 +1,40 @@\n+/*\n+ *  Copyright (C) 2008 Florian KÃ¶berle\n+ *\n+ *  This library is free software; you can redistribute it and/or\n+ *  modify it under the terms of the GNU General Public\n+ *  License, version 2, as published by the Free Software Foundation.\n+ *\n+ *  This library is distributed in the hope that it will be useful,\n+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+ *  General Public License for more details.\n+ *\n+ *  You should have received a copy of the GNU General Public\n+ *  License along with this library; if not, write to the Free Software\n+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301\n+ */\n+package org.spearce.jgit.pgm;\n+\n+import java.io.IOException;\n+\n+/**\n+ * A command have tasks like the \"git-add\", \"git-help\" or \"git-init\" console commands.\n+ * Instances of ${link Command} must be immutable.\n+ * @author Florian KÃ¶berle\n+ *\n+ */\n+public interface Command {\n+\t/**\n+\t * Executes the specified Command.\n+\t * @param args the arguments which you would pass to the console equivalent of the command.\n+\t * @throws IOException for some undefined reasons.\n+\t */\n+\tpublic void execute(String... args) throws IOException;\n+\n+\t/**\n+\t * \n+\t * @return a short description about what the command does. Short means in this context 5 - 10 words.\n+\t */\n+\tpublic String getShortDescription();\n+}\n\\ No newline at end of file\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/pgm/MainProgram.java b/org.spearce.jgit/src/org/spearce/jgit/pgm/MainProgram.java\nnew file mode 100644\nindex 0000000..72b0156\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/pgm/MainProgram.java\n@@ -0,0 +1,114 @@\n+/*\n+ *  Copyright (C) 2008 Florian KÃ¶berle\n+ *\n+ *  This library is free software; you can redistribute it and/or\n+ *  modify it under the terms of the GNU General Public\n+ *  License, version 2, as published by the Free Software Foundation.\n+ *\n+ *  This library is distributed in the hope that it will be useful,\n+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+ *  General Public License for more details.\n+ *\n+ *  You should have received a copy of the GNU General Public\n+ *  License along with this library; if not, write to the Free Software\n+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301\n+ */\n+package org.spearce.jgit.pgm;\n+\n+import java.io.IOException;\n+import java.util.Arrays;\n+import java.util.Collections;\n+import java.util.HashMap;\n+import java.util.Map;\n+import java.util.SortedMap;\n+import java.util.TreeMap;\n+\n+/**\n+ * A program which works similar like the command git, except that very view\n+ * arguments are supported jet.\n+ * \n+ * @author Florian KÃ¶berle\n+ * \n+ */\n+public class MainProgram {\n+\tprivate final static Map<String, Command> commandNameToObjectMap;\n+\n+\tstatic {\n+\t\tfinal Map<String, Command> commands = new HashMap<String, Command>();\n+\t\tcommands.put(\"help\", HelpCommand.INSTANCE);\n+\t\tcommandNameToObjectMap = Collections.unmodifiableMap(commands);\n+\t}\n+\n+\t/**\n+\t * Executes a command with some arguments. There are commands for creating\n+\t * git repositories, tracking files, etc.\n+\t * \n+\t * @param args\n+\t *            The first argument specifies the command which should be\n+\t *            executed. The other arguments are passed to the command.\n+\t * @throws IOException\n+\t *             for some reasons.\n+\t */\n+\tpublic static void main(String[] args) throws IOException {\n+\t\ttry {\n+\t\t\tif (args.length == 0) {\n+\t\t\t\tthrow new WrongCallException(\"Require one argument!\");\n+\t\t\t}\n+\t\t\tfinal Command command = commandNameToObjectMap.get(args[0]);\n+\t\t\tif (command == null) {\n+\t\t\t\tthrow new WrongCallException(\"Require one argument!\");\n+\t\t\t}\n+\t\t\tfinal String[] commandArguments = Arrays.copyOfRange(args, 1,\n+\t\t\t\t\targs.length);\n+\t\t\tcommand.execute(commandArguments);\n+\n+\t\t} catch (WrongCallException e) {\n+\t\t\tSystem.err.println(e.getMessage());\n+\t\t\tSystem.err.println();\n+\t\t\tHelpCommand.INSTANCE.execute();\n+\t\t\tSystem.exit(1);\n+\t\t}\n+\t}\n+\n+\tprivate static class WrongCallException extends Exception {\n+\t\tprivate static final long serialVersionUID = 3643362832429311084L;\n+\n+\t\tWrongCallException(String message) {\n+\t\t\tsuper(message);\n+\t\t}\n+\t}\n+\n+\tprivate static class HelpCommand implements Command {\n+\t\t/**\n+\t\t * Use this instance instead of creating a new ${link HelpCommand}. You\n+\t\t * don't need to create an instance of this class as it is immutable and\n+\t\t * not configurable.\n+\t\t */\n+\t\tpublic static HelpCommand INSTANCE = new HelpCommand();\n+\n+\t\tpublic void execute(String... args) throws IOException {\n+\t\t\tSystem.out\n+\t\t\t\t\t.println(\"Call this program with the following arguments:\");\n+\t\t\tSystem.out\n+\t\t\t\t\t.println(\"commandName commandArgument0 commandArgument1 ...\");\n+\t\t\tSystem.out.println();\n+\t\t\tSystem.out\n+\t\t\t\t\t.println(\"Currently the following commands are supported:\");\n+\t\t\tfinal SortedMap<String, Command> sortedCommandMap = new TreeMap<String, Command>(\n+\t\t\t\t\tMainProgram.commandNameToObjectMap);\n+\t\t\tfor (Map.Entry<String, Command> commandEntry : sortedCommandMap\n+\t\t\t\t\t.entrySet()) {\n+\t\t\t\tfinal String commandName = commandEntry.getKey();\n+\t\t\t\tfinal String commandDescription = commandEntry.getValue()\n+\t\t\t\t\t\t.getShortDescription();\n+\t\t\t\tSystem.out.printf(\"%#10s - %s%n\", commandName,\n+\t\t\t\t\t\tcommandDescription);\n+\t\t\t}\n+\t\t}\n+\n+\t\tpublic String getShortDescription() {\n+\t\t\treturn \"Displays some text about how to use this program.\";\n+\t\t}\n+\t}\n+}\n-- \n1.5.2.5\n"},{"id":"76508","messageId":"1210424440-13886-3-git-send-email-florianskarten@web.de","threadId":"13461","inReplyTo":"1210424440-13886-1-git-send-email-florianskarten@web.de","subject":"[JGIT PATCH 02/22] Replaced Java 6 API useage with Java 5 equivalent.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-05-10T13:00:20Z","receivedAt":"2008-05-10T13:00:20Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Signed-off-by: Florian Koeberle <florianskarten@web.de>\n---\n .../src/org/spearce/jgit/pgm/MainProgram.java      |    8 +++++---\n 1 files changed, 5 insertions(+), 3 deletions(-)\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/pgm/MainProgram.java b/org.spearce.jgit/src/org/spearce/jgit/pgm/MainProgram.java\nindex 72b0156..69cd96f 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/pgm/MainProgram.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/pgm/MainProgram.java\n@@ -17,7 +17,6 @@\n package org.spearce.jgit.pgm;\n \n import java.io.IOException;\n-import java.util.Arrays;\n import java.util.Collections;\n import java.util.HashMap;\n import java.util.Map;\n@@ -59,8 +58,11 @@ public class MainProgram {\n \t\t\tif (command == null) {\n \t\t\t\tthrow new WrongCallException(\"Require one argument!\");\n \t\t\t}\n-\t\t\tfinal String[] commandArguments = Arrays.copyOfRange(args, 1,\n-\t\t\t\t\targs.length);\n+\n+\t\t\tfinal String[] commandArguments = new String[args.length - 1];\n+\t\t\tSystem.arraycopy(args, 1, commandArguments, 0,\n+\t\t\t\t\tcommandArguments.length);\n+\n \t\t\tcommand.execute(commandArguments);\n \n \t\t} catch (WrongCallException e) {\n-- \n1.5.2.5\n"},{"id":"76516","messageId":"1210424440-13886-4-git-send-email-florianskarten@web.de","threadId":"13461","inReplyTo":"1210424440-13886-1-git-send-email-florianskarten@web.de","subject":"[JGIT PATCH 03/22] Added a class Project which represents a project directory and it's repository.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-05-10T13:00:21Z","receivedAt":"2008-05-10T13:00:21Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Signed-off-by: Florian Koeberle <florianskarten@web.de>\n---\n .../src/org/spearce/jgit/lib/GitPathConstants.java |   28 +++++++++\n .../src/org/spearce/jgit/lib/Project.java          |   63 ++++++++++++++++++++\n .../src/org/spearce/jgit/lib/ProjectFactory.java   |   57 ++++++++++++++++++\n 3 files changed, 148 insertions(+), 0 deletions(-)\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/GitPathConstants.java\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/Project.java\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/ProjectFactory.java\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/GitPathConstants.java b/org.spearce.jgit/src/org/spearce/jgit/lib/GitPathConstants.java\nnew file mode 100644\nindex 0000000..3d99d33\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/GitPathConstants.java\n@@ -0,0 +1,28 @@\n+package org.spearce.jgit.lib;\n+\n+/**\n+ * Collection of constants related to the git repository directory layout.\n+ * \n+ */\n+public class GitPathConstants {\n+\t/**\n+\t * The name of the repository directory in the project directory.\n+\t */\n+\tpublic static final String REPOSITORY_DIRECTORY_NAME = \".git\";\n+\n+\t/**\n+\t * Contains the name of the objects directory in the repository directory.\n+\t */\n+\tpublic static final String OBJECTS_DIRECTORY_NAME = \"objects\";\n+\n+\t/**\n+\t * Contains the name of the refs directory in the repository directory.\n+\t */\n+\tpublic static final String REFS_DIRECTORY_NAME = \"refs\";\n+\t\n+\t/**\n+\t * Contains the name of the HEAD file in the repository directory.\n+\t */\n+\tpublic static final String HEAD_FILE_NAME = \"HEAD\";\n+\n+}\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Project.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Project.java\nnew file mode 100644\nindex 0000000..6e72486\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Project.java\n@@ -0,0 +1,63 @@\n+/*\n+ *  Copyright (C) 2008 Florian KÃ¶berle\n+ *\n+ *  This library is free software; you can redistribute it and/or\n+ *  modify it under the terms of the GNU General Public\n+ *  License, version 2, as published by the Free Software Foundation.\n+ *\n+ *  This library is distributed in the hope that it will be useful,\n+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+ *  General Public License for more details.\n+ *\n+ *  You should have received a copy of the GNU General Public\n+ *  License along with this library; if not, write to the Free Software\n+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301\n+ */\n+package org.spearce.jgit.lib;\n+\n+import java.io.File;\n+\n+/**\n+ * Represents a project controlled by git. Use {@link ProjectFactory} in order to create an object of this class.\n+ * @author Florian KÃ¶berle\n+ *\n+ */\n+public class Project {\n+\tprivate final File directory;\n+\n+\tprivate final Repository repository;\n+\n+\t/**\n+\t * This constructor should be only used by the class {@link ProjectFactory}.\n+\t * @param directory defines the value of the directory field.\n+\t * @param repository defines the value of the repository field.\n+\t */\n+\tProject(File directory, Repository repository) {\n+\t\tthis.directory = directory;\n+\t\tthis.repository = repository;\n+\t}\n+\n+\t/**\n+\t * \n+\t * @return the directory which contains the files of the project. Usually this directory contain a .git directory with the repository.\n+\t */\n+\tpublic File getDirectory() {\n+\t\treturn directory;\n+\t}\n+\n+\t/**\n+\t * @return the {@link Repository} object of the project.\n+\t */\n+\tpublic Repository getRepository() {\n+\t\treturn repository;\n+\t}\n+\n+\t/**\n+\t * Closes the git repository of this project.\n+\t */\n+\tpublic void closeRepository() {\n+\t\trepository.close();\n+\t}\n+\n+}\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/ProjectFactory.java b/org.spearce.jgit/src/org/spearce/jgit/lib/ProjectFactory.java\nnew file mode 100644\nindex 0000000..b4e5660\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/ProjectFactory.java\n@@ -0,0 +1,57 @@\n+/*\n+ *  Copyright (C) 2008 Florian KÃ¶berle\n+ *\n+ *  This library is free software; you can redistribute it and/or\n+ *  modify it under the terms of the GNU General Public\n+ *  License, version 2, as published by the Free Software Foundation.\n+ *\n+ *  This library is distributed in the hope that it will be useful,\n+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+ *  General Public License for more details.\n+ *\n+ *  You should have received a copy of the GNU General Public\n+ *  License along with this library; if not, write to the Free Software\n+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301\n+ */\n+package org.spearce.jgit.lib;\n+\n+import java.io.File;\n+import java.io.IOException;\n+import static org.spearce.jgit.lib.GitPathConstants.REPOSITORY_DIRECTORY_NAME;\n+\n+/**\n+ * Creates a new {@link Project} and initialize a repository for it. \n+ * \n+ * @author Florian KÃ¶berle\n+ * \n+ */\n+public class ProjectFactory {\n+\n+\t/**\n+\t * @param projectDirectory\n+\t *            the directory with the project files.\n+\t * @return a new project with a new and open repository.\n+\t * @throws IOException\n+\t *             thrown by {@link Repository#create()}\n+\t */\n+\tpublic Project createProject(File projectDirectory) throws IOException {\n+\t\tfinal File gitDirectory = new File(projectDirectory, REPOSITORY_DIRECTORY_NAME);\n+\t\tif (gitDirectory.exists()) {\n+\t\t\tthrow new IllegalArgumentException(\n+\t\t\t\t\t\"Repository exists in given project directory.\");\n+\t\t}\n+\t\tfinal Repository repository = new Repository(gitDirectory);\n+\t\ttry {\n+\t\t\trepository.create();\n+\t\t\treturn new Project(projectDirectory, repository);\n+\t\t} catch (RuntimeException e) {\n+\t\t\trepository.close();\n+\t\t\tthrow e;\n+\t\t} catch (IOException e) {\n+\t\t\trepository.close();\n+\t\t\tthrow e;\n+\t\t}\n+\t}\n+\n+}\n-- \n1.5.2.5\n"},{"id":"76515","messageId":"1210424440-13886-5-git-send-email-florianskarten@web.de","threadId":"13461","inReplyTo":"1210424440-13886-1-git-send-email-florianskarten@web.de","subject":"[JGIT PATCH 04/22] Added a \"init\" command to the git like command line tool.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-05-10T13:00:22Z","receivedAt":"2008-05-10T13:00:22Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Signed-off-by: Florian Koeberle <florianskarten@web.de>\n---\n .../src/org/spearce/jgit/pgm/InitCommand.java      |   71 ++++++++++++++++++++\n .../src/org/spearce/jgit/pgm/MainProgram.java      |    1 +\n 2 files changed, 72 insertions(+), 0 deletions(-)\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/pgm/InitCommand.java\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/pgm/InitCommand.java b/org.spearce.jgit/src/org/spearce/jgit/pgm/InitCommand.java\nnew file mode 100644\nindex 0000000..4bc7ca8\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/pgm/InitCommand.java\n@@ -0,0 +1,71 @@\n+/*\n+ *  Copyright (C) 2008 Florian KÃ¶berle\n+ *\n+ *  This library is free software; you can redistribute it and/or\n+ *  modify it under the terms of the GNU General Public\n+ *  License, version 2, as published by the Free Software Foundation.\n+ *\n+ *  This library is distributed in the hope that it will be useful,\n+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+ *  General Public License for more details.\n+ *\n+ *  You should have received a copy of the GNU General Public\n+ *  License along with this library; if not, write to the Free Software\n+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301\n+ */\n+package org.spearce.jgit.pgm;\n+\n+import java.io.File;\n+import java.io.IOException;\n+\n+import org.spearce.jgit.lib.Project;\n+import org.spearce.jgit.lib.ProjectFactory;\n+\n+import static java.lang.String.format;\n+\n+/**\n+ * This class is immutable. It's {@link #execute} method is used to create git\n+ * repositories.\n+ * \n+ * @author Florian KÃ¶berle\n+ * \n+ */\n+public class InitCommand implements Command {\n+\t/**\n+\t * Use this instance instead of creating a new ${link InitCommand}. You\n+\t * don't need to create an instance of this class as it is immutable and not\n+\t * configurable.\n+\t */\n+\tpublic static InitCommand INSTANCE = new InitCommand();\n+\n+\tpublic void execute(String... args) throws IOException {\n+\t\tfinal String currentDirectoryPathString = System\n+\t\t\t\t.getProperty(\"user.dir\");\n+\t\tif (currentDirectoryPathString == null) {\n+\t\t\tthrow new IOException(\"Unable to get current working directory\");\n+\t\t}\n+\t\tfinal File currentDirectoryPath = new File(currentDirectoryPathString);\n+\t\tif (!currentDirectoryPath.isDirectory()) {\n+\t\t\tfinal String message = format(\n+\t\t\t\t\t\"No directory found at \\\"%s\\\". It was the current working directory at program start.\",\n+\t\t\t\t\tcurrentDirectoryPathString);\n+\t\t\tthrow new IOException(message);\n+\t\t}\n+\t\tfinal ProjectFactory projectFactory = new ProjectFactory();\n+\n+\t\tfinal Project project = projectFactory\n+\t\t\t\t.createProject(currentDirectoryPath);\n+\t\ttry {\n+\t\t\tSystem.out.printf(\"Created a git repository at: %s%n\", project\n+\t\t\t\t\t.getRepository().getDirectory());\n+\t\t} finally {\n+\t\t\tproject.closeRepository();\n+\t\t}\n+\n+\t}\n+\n+\tpublic String getShortDescription() {\n+\t\treturn \"Creates an empty git repository.\";\n+\t}\n+}\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/pgm/MainProgram.java b/org.spearce.jgit/src/org/spearce/jgit/pgm/MainProgram.java\nindex 69cd96f..7601f31 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/pgm/MainProgram.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/pgm/MainProgram.java\n@@ -35,6 +35,7 @@ public class MainProgram {\n \n \tstatic {\n \t\tfinal Map<String, Command> commands = new HashMap<String, Command>();\n+\t\tcommands.put(\"init\", InitCommand.INSTANCE);\n \t\tcommands.put(\"help\", HelpCommand.INSTANCE);\n \t\tcommandNameToObjectMap = Collections.unmodifiableMap(commands);\n \t}\n-- \n1.5.2.5\n"},{"id":"76509","messageId":"1210424440-13886-6-git-send-email-florianskarten@web.de","threadId":"13461","inReplyTo":"1210424440-13886-1-git-send-email-florianskarten@web.de","subject":"[JGIT PATCH 05/22] Added ProjectSeeker class.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-05-10T13:00:23Z","receivedAt":"2008-05-10T13:00:23Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Signed-off-by: Florian Koeberle <florianskarten@web.de>\n---\n .../src/org/spearce/jgit/lib/Project.java          |    5 +-\n .../src/org/spearce/jgit/lib/ProjectSeeker.java    |  118 ++++++++++++++++++++\n 2 files changed, 122 insertions(+), 1 deletions(-)\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/ProjectSeeker.java\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Project.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Project.java\nindex 6e72486..f6b6a17 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/Project.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Project.java\n@@ -19,7 +19,10 @@ package org.spearce.jgit.lib;\n import java.io.File;\n \n /**\n- * Represents a project controlled by git. Use {@link ProjectFactory} in order to create an object of this class.\n+ * Represents a project controlled by git. Use {@link ProjectFactory} in order to create an object of this class. If you\n+ * don't want to create a new repository, but need a new {@link Project}\n+ * instance then use {@link ProjectSeeker}.\n+ * \n  * @author Florian KÃ¶berle\n  *\n  */\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/ProjectSeeker.java b/org.spearce.jgit/src/org/spearce/jgit/lib/ProjectSeeker.java\nnew file mode 100644\nindex 0000000..3aa5284\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/ProjectSeeker.java\n@@ -0,0 +1,118 @@\n+/*\n+ *  Copyright (C) 2008 Florian KÃ¶berle\n+ *\n+ *  This library is free software; you can redistribute it and/or\n+ *  modify it under the terms of the GNU General Public\n+ *  License, version 2, as published by the Free Software Foundation.\n+ *\n+ *  This library is distributed in the hope that it will be useful,\n+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+ *  General Public License for more details.\n+ *\n+ *  You should have received a copy of the GNU General Public\n+ *  License along with this library; if not, write to the Free Software\n+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301\n+ */\n+package org.spearce.jgit.lib;\n+\n+import java.io.File;\n+import java.io.IOException;\n+import static org.spearce.jgit.lib.GitPathConstants.OBJECTS_DIRECTORY_NAME;\n+import static org.spearce.jgit.lib.GitPathConstants.REPOSITORY_DIRECTORY_NAME;\n+import static org.spearce.jgit.lib.GitPathConstants.REFS_DIRECTORY_NAME;\n+import static org.spearce.jgit.lib.GitPathConstants.HEAD_FILE_NAME;\n+\n+/**\n+ * Use this class to create instances of {@link Project}.\n+ * \n+ * @author Florian KÃ¶berle\n+ * \n+ */\n+public class ProjectSeeker {\n+\n+\t/**\n+\t * Find the git repository for the current working directory.\n+\t * \n+\t * @return a {@link Repository}.\n+\t * @throws IOException\n+\t *             if the system property user.dir isn't set or if it is\n+\t *             invalid.\n+\t */\n+\tpublic Project findProject() throws IOException {\n+\t\tfinal String workingDirectoryPath = System.getProperty(\"user.dir\");\n+\t\tif (workingDirectoryPath == null) {\n+\t\t\tthrow new IOException(\"unable to get working directory\");\n+\t\t}\n+\t\tfinal File workingDirectoryFile = new File(workingDirectoryPath);\n+\t\tif (!workingDirectoryFile.exists()) {\n+\t\t\tthrow new IOException(\"Working directory path is invalid\");\n+\t\t}\n+\t\treturn findProject(workingDirectoryFile);\n+\t}\n+\n+\t/**\n+\t * Checks if a path is a valid git repository. Works similar like the method\n+\t * is_git_directory from the original setup.c file.\n+\t * \n+\t * @param directory\n+\t *            the path which should be checked.\n+\t * @return true if the path is a valid git repository.\n+\t */\n+\tprivate boolean isRepository(File directory) {\n+\t\tif (!directory.isDirectory()) {\n+\t\t\treturn false;\n+\t\t}\n+\n+\t\tfinal File objectDirectory = new File(directory, OBJECTS_DIRECTORY_NAME);\n+\t\tif (!objectDirectory.isDirectory()) {\n+\t\t\treturn false;\n+\t\t}\n+\n+\t\tfinal File refsDirectory = new File(directory, REFS_DIRECTORY_NAME);\n+\t\tif (!refsDirectory.isDirectory()) {\n+\t\t\treturn false;\n+\t\t}\n+\n+\t\tfinal File head = new File(directory, HEAD_FILE_NAME);\n+\t\tif (!hasValidateHeadRef(head)) {\n+\t\t\treturn false;\n+\t\t}\n+\n+\t\treturn true;\n+\t}\n+\n+\t/**\n+\t * Checks for example if a path is a valid HEAD file. Should do the same\n+\t * like validate_headref from path.c.\n+\t * \n+\t * @param path\n+\t *            is the path of the HEAD file.\n+\t * @return true if it has a valid head reference.\n+\t */\n+\tprivate static final boolean hasValidateHeadRef(File path) {\n+\t\treturn true; // TODO stub. view int validate_headref(const char\n+\t\t// *path) at path.c\n+\t}\n+\n+\tprivate Project findProject(File directory) throws IOException {\n+\t\tFile currentDirectory = directory.getAbsoluteFile();\n+\t\twhile (true) {\n+\t\t\tfinal File commonGitDirectory = new File(directory,\n+\t\t\t\t\tREPOSITORY_DIRECTORY_NAME);\n+\t\t\tif (isRepository(commonGitDirectory)) {\n+\t\t\t\treturn new Project(currentDirectory, new Repository(\n+\t\t\t\t\t\tcommonGitDirectory));\n+\t\t\t}\n+\n+\t\t\tif (isRepository(currentDirectory)) {\n+\t\t\t\treturn new Project(null, new Repository(currentDirectory));\n+\t\t\t}\n+\t\t\tcurrentDirectory = currentDirectory.getParentFile();\n+\t\t\tif (currentDirectory == null) {\n+\t\t\t\tthrow new IOException(\"Can't find git repository\");\n+\t\t\t}\n+\t\t}\n+\n+\t}\n+}\n-- \n1.5.2.5\n"},{"id":"76510","messageId":"1210424440-13886-7-git-send-email-florianskarten@web.de","threadId":"13461","inReplyTo":"1210424440-13886-1-git-send-email-florianskarten@web.de","subject":"[JGIT PATCH 06/22] Added the interface FilePattern.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-05-10T13:00:24Z","receivedAt":"2008-05-10T13:00:24Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Signed-off-by: Florian Koeberle <florianskarten@web.de>\n---\n .../jgit/lib/fileiteration/FilePattern.java        |  107 ++++++++++++++++++++\n 1 files changed, 107 insertions(+), 0 deletions(-)\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/FilePattern.java\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/FilePattern.java b/org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/FilePattern.java\nnew file mode 100644\nindex 0000000..01edbd4\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/FilePattern.java\n@@ -0,0 +1,107 @@\n+/*\n+ *  Copyright (C) 2008 Florian KÃ¶berle\n+ *\n+ *  This library is free software; you can redistribute it and/or\n+ *  modify it under the terms of the GNU General Public\n+ *  License, version 2, as published by the Free Software Foundation.\n+ *\n+ *  This library is distributed in the hope that it will be useful,\n+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+ *  General Public License for more details.\n+ *\n+ *  You should have received a copy of the GNU General Public\n+ *  License along with this library; if not, write to the Free Software\n+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301\n+ */\n+package org.spearce.jgit.lib.fileiteration;\n+\n+/**\n+ * A {@link FilePattern} can be used to check if files in a directory matches a\n+ * pattern. It provides with the {@link #getPatternForSubDirectory(String)}\n+ * method {@link FilePattern}s for sub directories.\n+ * \n+ * Implementations of this interface should be immutable.\n+ * \n+ * @author Florian Koeberle\n+ * \n+ */\n+interface FilePattern {\n+\t/**\n+\t * This pattern instance matches always.\n+\t */\n+\tpublic static final FilePattern MATCH_ALWAYS = new FilePattern() {\n+\n+\t\tpublic FilePattern getPatternForSubDirectory(String directoryName) {\n+\t\t\treturn MATCH_ALWAYS;\n+\t\t}\n+\n+\t\tpublic boolean match(String fileName, boolean fileIsDirectory) {\n+\t\t\treturn true;\n+\t\t}\n+\n+\t\tpublic boolean canMatchAtThisDirectoryLevel() {\n+\t\t\treturn true;\n+\t\t}\n+\n+\t\tpublic boolean isSameForSubDirectories() {\n+\t\t\treturn true;\n+\t\t}\n+\t};\n+\n+\t/**\n+\t * This pattern instance matches never.\n+\t */\n+\tpublic static final FilePattern MATCH_NEVER = new FilePattern() {\n+\n+\t\tpublic FilePattern getPatternForSubDirectory(String directoryName) {\n+\t\t\treturn MATCH_NEVER;\n+\t\t}\n+\n+\t\tpublic boolean match(String fileName, boolean fileIsDirectory) {\n+\t\t\treturn false;\n+\t\t}\n+\n+\t\tpublic boolean canMatchAtThisDirectoryLevel() {\n+\t\t\treturn false;\n+\t\t}\n+\n+\t\tpublic boolean isSameForSubDirectories() {\n+\t\t\treturn true;\n+\t\t}\n+\t};\n+\n+\t/**\n+\t * @param fileName\n+\t *            the name of the file or directory\n+\t * @param fileIsDirectory\n+\t *            determines if the file is a directory.\n+\t * @return true if the pattern matches.\n+\t */\n+\tboolean match(String fileName, boolean fileIsDirectory);\n+\n+\t/**\n+\t * \n+\t * @param directoryName\n+\t *            the name of a subdirectory.\n+\t * @return a pattern which can be used to match files in sub directories. A\n+\t *         user may check if the returned value is {@link #MATCH_NEVER} in\n+\t *         order to do some performance optimizations.\n+\t * \n+\t */\n+\tFilePattern getPatternForSubDirectory(String directoryName);\n+\n+\t/**\n+\t * This method can be used to generate an smaller list of rules, which can\n+\t * match.\n+\t * \n+\t * @return true if {@link #match(String, boolean)} returns always false.\n+\t */\n+\tboolean canMatchAtThisDirectoryLevel();\n+\n+\t/**\n+\t * @return true if {@link #getPatternForSubDirectory(String)} returns true\n+\t *         for every value.\n+\t */\n+\tboolean isSameForSubDirectories();\n+}\n\\ No newline at end of file\n-- \n1.5.2.5\n"},{"id":"76518","messageId":"1210424440-13886-8-git-send-email-florianskarten@web.de","threadId":"13461","inReplyTo":"1210424440-13886-1-git-send-email-florianskarten@web.de","subject":"[JGIT PATCH 07/22] Added the class Rule.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-05-10T13:00:25Z","receivedAt":"2008-05-10T13:00:25Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Signed-off-by: Florian Koeberle <florianskarten@web.de>\n---\n .../org/spearce/jgit/lib/fileiteration/Rule.java   |   58 ++++++++++++++++++++\n 1 files changed, 58 insertions(+), 0 deletions(-)\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/Rule.java\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/Rule.java b/org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/Rule.java\nnew file mode 100644\nindex 0000000..733bb6a\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/Rule.java\n@@ -0,0 +1,58 @@\n+/*\n+ *  Copyright (C) 2008 Florian KÃ¶berle\n+ *\n+ *  This library is free software; you can redistribute it and/or\n+ *  modify it under the terms of the GNU General Public\n+ *  License, version 2, as published by the Free Software Foundation.\n+ *\n+ *  This library is distributed in the hope that it will be useful,\n+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+ *  General Public License for more details.\n+ *\n+ *  You should have received a copy of the GNU General Public\n+ *  License along with this library; if not, write to the Free Software\n+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301\n+ */\n+package org.spearce.jgit.lib.fileiteration;\n+\n+/**\n+ * A Rule defines what to do with a files which match a specified\n+ * {@link FilePattern}.\n+ */\n+class Rule {\n+\tprivate boolean ignoreAtMatch;\n+\n+\tprivate FilePattern pattern;\n+\n+\tRule(boolean ignoreAtMatch, FilePattern pattern) {\n+\t\tthis.ignoreAtMatch = ignoreAtMatch;\n+\t\tthis.pattern = pattern;\n+\t}\n+\n+\tFilePattern getPattern() {\n+\t\treturn pattern;\n+\t}\n+\n+\tboolean isIgnoreAtMatch() {\n+\t\treturn ignoreAtMatch;\n+\t}\n+\n+\tRule getRuleForSubDirectory(String directoryName) {\n+\t\tfinal FilePattern subPattern = pattern\n+\t\t\t\t.getPatternForSubDirectory(directoryName);\n+\t\tif (subPattern == pattern) {\n+\t\t\treturn this;\n+\t\t}\n+\t\treturn new Rule(ignoreAtMatch, subPattern);\n+\t}\n+\n+\tboolean canMatchAtThisDirectoryLevel() {\n+\t\treturn pattern.canMatchAtThisDirectoryLevel();\n+\t}\n+\n+\tboolean isSameForSubDirectories() {\n+\t\treturn pattern.isSameForSubDirectories();\n+\t}\n+\n+}\n-- \n1.5.2.5\n"},{"id":"76517","messageId":"1210424440-13886-9-git-send-email-florianskarten@web.de","threadId":"13461","inReplyTo":"1210424440-13886-1-git-send-email-florianskarten@web.de","subject":"[JGIT PATCH 08/22] Added the iterface Rules.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-05-10T13:00:26Z","receivedAt":"2008-05-10T13:00:26Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Signed-off-by: Florian Koeberle <florianskarten@web.de>\n---\n .../org/spearce/jgit/lib/fileiteration/Rules.java  |  101 ++++++++++++++++++++\n 1 files changed, 101 insertions(+), 0 deletions(-)\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/Rules.java\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/Rules.java b/org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/Rules.java\nnew file mode 100644\nindex 0000000..1334a22\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/Rules.java\n@@ -0,0 +1,101 @@\n+/*\n+ *  Copyright (C) 2008 Florian KÃ¶berle\n+ *\n+ *  This library is free software; you can redistribute it and/or\n+ *  modify it under the terms of the GNU General Public\n+ *  License, version 2, as published by the Free Software Foundation.\n+ *\n+ *  This library is distributed in the hope that it will be useful,\n+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+ *  General Public License for more details.\n+ *\n+ *  You should have received a copy of the GNU General Public\n+ *  License along with this library; if not, write to the Free Software\n+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301\n+ */\n+package org.spearce.jgit.lib.fileiteration;\n+\n+/**\n+ * A {@link Rules} instances defines ignore or do not ignore rules for files in\n+ * a directory. It can't directly be used to match files in sub directories, but\n+ * provides a method {@link #getRulesForSubDirectory}.\n+ * \n+ * @author Florian KÃ¶berle\n+ * \n+ */\n+public interface Rules {\n+\n+\t/**\n+\t * Provides the instance of {@link IgnoreAllRules}.\n+\t */\n+\tpublic static final Rules IGNORE_ALL = new IgnoreAllRules();\n+\n+\t/**\n+\t * Provides the instance of {@link IgnoreNothingRules}.\n+\t */\n+\tpublic static final Rules IGNORE_NOTHING = new IgnoreNothingRules();\n+\n+\t/**\n+\t * @param fileName\n+\t *            the name of the file or directory.\n+\t * @param fileIsDirectory\n+\t *            should be true if the file is a directory.\n+\t * @return true if the file or directory should be ignored.\n+\t */\n+\tpublic abstract boolean toIgnore(String fileName, boolean fileIsDirectory);\n+\n+\t/**\n+\t * @param directoryName\n+\t *            the sub directory for which you want an {@link Rules}\n+\t *            instance.\n+\t * @return an {@link Rules} instance, which can be used to check files in\n+\t *         the specified sub directory.\n+\t */\n+\tpublic abstract Rules getRulesForSubDirectory(String directoryName);\n+\n+\t/**\n+\t * This implementation ignores everything.\n+\t */\n+\tpublic static final class IgnoreAllRules implements Rules {\n+\t\tprivate IgnoreAllRules() {\n+\t\t\t// declared to make the constructor private\n+\t\t}\n+\n+\t\tpublic Rules getRulesForSubDirectory(String directoryName) {\n+\t\t\treturn this;\n+\t\t}\n+\n+\t\tpublic boolean toIgnore(String fileName, boolean fileIsDirectory) {\n+\t\t\treturn true;\n+\t\t}\n+\n+\t\t@Override\n+\t\tpublic String toString() {\n+\t\t\treturn \"ignore all rules\";\n+\t\t}\n+\t}\n+\n+\t/**\n+\t * This implementation ignores nothing.\n+\t */\n+\tpublic static final class IgnoreNothingRules implements Rules {\n+\t\tprivate IgnoreNothingRules() {\n+\t\t\t// declared to make the constructor private\n+\t\t}\n+\t\t\n+\t\tpublic Rules getRulesForSubDirectory(String directoryName) {\n+\t\t\treturn this;\n+\t\t}\n+\n+\t\tpublic boolean toIgnore(String fileName, boolean fileIsDirectory) {\n+\t\t\treturn false;\n+\t\t}\n+\n+\t\t@Override\n+\t\tpublic String toString() {\n+\t\t\treturn \"ignore nothing rules\";\n+\t\t}\n+\t}\n+\n+}\n\\ No newline at end of file\n-- \n1.5.2.5\n"},{"id":"76522","messageId":"1210424440-13886-10-git-send-email-florianskarten@web.de","threadId":"13461","inReplyTo":"1210424440-13886-1-git-send-email-florianskarten@web.de","subject":"[JGIT PATCH 09/22] Added the class FileTreeIterator and a test for it.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-05-10T13:00:27Z","receivedAt":"2008-05-10T13:00:27Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Signed-off-by: Florian Koeberle <florianskarten@web.de>\n---\n .../lib/fileiteration/FileTreeIteratorTest.java    |  112 ++++++++++++++++++++\n .../jgit/lib/fileiteration/FileTreeIterator.java   |  110 +++++++++++++++++++\n 2 files changed, 222 insertions(+), 0 deletions(-)\n create mode 100644 org.spearce.jgit.test/tst/org/spearce/jgit/lib/fileiteration/FileTreeIteratorTest.java\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/FileTreeIterator.java\n\ndiff --git a/org.spearce.jgit.test/tst/org/spearce/jgit/lib/fileiteration/FileTreeIteratorTest.java b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/fileiteration/FileTreeIteratorTest.java\nnew file mode 100644\nindex 0000000..a7384d3\n--- /dev/null\n+++ b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/fileiteration/FileTreeIteratorTest.java\n@@ -0,0 +1,112 @@\n+/*\n+ *  Copyright (C) 2008 Florian KÃ¶berle\n+ *\n+ *  This library is free software; you can redistribute it and/or\n+ *  modify it under the terms of the GNU General Public\n+ *  License, version 2, as published by the Free Software Foundation.\n+ *\n+ *  This library is distributed in the hope that it will be useful,\n+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+ *  General Public License for more details.\n+ *\n+ *  You should have received a copy of the GNU General Public\n+ *  License along with this library; if not, write to the Free Software\n+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301\n+ */\n+package org.spearce.jgit.lib.fileiteration;\n+\n+import java.io.File;\n+import java.util.HashSet;\n+import java.util.Iterator;\n+import java.util.Set;\n+\n+import junit.framework.TestCase;\n+\n+public class FileTreeIteratorTest extends TestCase {\n+\tprivate String DIRECTORY_A_NAME = \"a\";\n+\n+\tprivate String DIRECTORY_AB_NAME = \"b\";\n+\n+\tprivate File projectDirectory;\n+\n+\tprivate File fileB;\n+\n+\tprivate File directoryA;\n+\n+\tprivate File directoryAB;\n+\n+\tprivate File fileABA;\n+\n+\tprivate File directoryAC;\n+\n+\tprivate File fileACA;\n+\n+\tprivate File fileACB;\n+\n+\t@Override\n+\tprotected void setUp() throws Exception {\n+\t\tthis.projectDirectory = File.createTempFile(\"FileTreeIteratorTest\", \"\");\n+\t\tprojectDirectory.delete();\n+\t\tprojectDirectory.mkdir();\n+\t\tprojectDirectory.deleteOnExit();\n+\n+\t\tthis.directoryA = new File(projectDirectory, DIRECTORY_A_NAME);\n+\t\tdirectoryA.mkdir();\n+\n+\t\tthis.directoryAB = new File(directoryA, DIRECTORY_AB_NAME);\n+\t\tdirectoryAB.mkdir();\n+\n+\t\tthis.fileABA = new File(directoryAB, \"a.y\");\n+\t\tfileABA.createNewFile();\n+\n+\t\tthis.directoryAC = new File(directoryA, \"c\");\n+\t\tthis.directoryAC.mkdir();\n+\n+\t\tthis.fileACA = new File(directoryAC, \"a.x\");\n+\t\tfileACA.createNewFile();\n+\n+\t\tthis.fileACB = new File(directoryAC, \"b.y\");\n+\t\tfileACB.createNewFile();\n+\n+\t\tthis.fileB = new File(projectDirectory, \"b.x\");\n+\t\tfileB.createNewFile();\n+\t}\n+\n+\tpublic void testFileTreeIterator() {\n+\t\tfinal Iterator<File> iterator = new FileTreeIterator(projectDirectory,\n+\t\t\t\tRules.IGNORE_NOTHING, false);\n+\t\tfinal Set<File> actualPathes = new HashSet<File>();\n+\t\twhile (iterator.hasNext()) {\n+\t\t\tfinal File next = iterator.next();\n+\t\t\tassertFalse(actualPathes.contains(next));\n+\t\t\tactualPathes.add(next);\n+\t\t}\n+\n+\t\tfinal Set<File> expectedPathes = new HashSet<File>();\n+\t\texpectedPathes.add(directoryA);\n+\t\texpectedPathes.add(fileB);\n+\t\texpectedPathes.add(directoryAB);\n+\t\texpectedPathes.add(fileABA);\n+\t\texpectedPathes.add(directoryAC);\n+\t\texpectedPathes.add(fileACA);\n+\t\texpectedPathes.add(fileACB);\n+\t\tassertEquals(expectedPathes, actualPathes);\n+\n+\t}\n+\n+\tpublic void testFileTreeIteratorWithIgnoreAllRules() {\n+\t\tfinal Iterator<File> iterator = new FileTreeIterator(projectDirectory,\n+\t\t\t\tRules.IGNORE_ALL, false);\n+\t\tfinal Set<File> actualPathes = new HashSet<File>();\n+\t\twhile (iterator.hasNext()) {\n+\t\t\tfinal File next = iterator.next();\n+\t\t\tassertFalse(actualPathes.contains(next));\n+\t\t\tactualPathes.add(next);\n+\t\t}\n+\n+\t\tassertEquals(0, actualPathes.size());\n+\n+\t}\n+\n+}\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/FileTreeIterator.java b/org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/FileTreeIterator.java\nnew file mode 100644\nindex 0000000..5e76739\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/FileTreeIterator.java\n@@ -0,0 +1,110 @@\n+/*\n+ *  Copyright (C) 2008 Florian KÃ¶berle\n+ *\n+ *  This library is free software; you can redistribute it and/or\n+ *  modify it under the terms of the GNU General Public\n+ *  License, version 2, as published by the Free Software Foundation.\n+ *\n+ *  This library is distributed in the hope that it will be useful,\n+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+ *  General Public License for more details.\n+ *\n+ *  You should have received a copy of the GNU General Public\n+ *  License along with this library; if not, write to the Free Software\n+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301\n+ */\n+package org.spearce.jgit.lib.fileiteration;\n+\n+import java.io.File;\n+import java.util.EmptyStackException;\n+import java.util.Iterator;\n+import java.util.NoSuchElementException;\n+import java.util.Stack;\n+\n+class FileTreeIterator implements Iterator<File> {\n+\tprivate final Stack<File> remainingPathes;\n+\n+\tprivate final Stack<Directory> remainingDirectories;\n+\n+\t/**\n+\t * Creates a new Iterator which allows to iterate over the content of the\n+\t * specified rootDirectory. The rootDirectory itself is never included.\n+\t * \n+\t * @param rootDirectory\n+\t *            the directory tree to iterate over.\n+\t * @param ignoreRules\n+\t *            defines which paths are included and which aren't.\n+\t * @param includeRootDirectory\n+\t *            the iterator will return the rootDirectory if this is flag is\n+\t *            true.\n+\t */\n+\tFileTreeIterator(File rootDirectory, Rules ignoreRules,\n+\t\t\tboolean includeRootDirectory) {\n+\t\tremainingPathes = new Stack<File>();\n+\t\tif (includeRootDirectory) {\n+\t\t\tremainingPathes.add(rootDirectory);\n+\t\t}\n+\t\tremainingDirectories = new Stack<Directory>();\n+\t\tremainingDirectories.add(new Directory(rootDirectory, ignoreRules));\n+\t}\n+\n+\tpublic boolean hasNext() {\n+\t\tfindMorePathesIfNessesary();\n+\t\treturn !remainingPathes.empty();\n+\t}\n+\n+\tvoid findMorePathesIfNessesary() {\n+\t\tif (remainingPathes.isEmpty()) {\n+\t\t\tfindMorePathes();\n+\t\t}\n+\t}\n+\n+\tvoid findMorePathes() {\n+\t\twhile (!remainingDirectories.isEmpty() && remainingPathes.isEmpty()) {\n+\t\t\tfinal Directory directory = remainingDirectories.pop();\n+\t\t\tfinal File[] pathes = directory.path.listFiles();\n+\t\t\tfor (File path : pathes) {\n+\t\t\t\tfinal boolean fileIsDirectory = path.isDirectory();\n+\t\t\t\tif (fileIsDirectory) {\n+\t\t\t\t\tfinal Rules subDirectoryIgnoreRules = directory.ignoreRules\n+\t\t\t\t\t\t\t.getRulesForSubDirectory(path.getName());\n+\t\t\t\t\tif (subDirectoryIgnoreRules != Rules.IGNORE_ALL) {\n+\t\t\t\t\t\tfinal Directory subDirectory = new Directory(path,\n+\t\t\t\t\t\t\t\tsubDirectoryIgnoreRules);\n+\t\t\t\t\t\tremainingDirectories.add(subDirectory);\n+\t\t\t\t\t}\n+\t\t\t\t}\n+\t\t\t\tif (!directory.ignoreRules.toIgnore(path.getName(),\n+\t\t\t\t\t\tfileIsDirectory)) {\n+\t\t\t\t\tremainingPathes.add(path);\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\tpublic File next() {\n+\t\tfindMorePathesIfNessesary();\n+\t\ttry {\n+\t\t\treturn remainingPathes.pop();\n+\t\t} catch (EmptyStackException e) {\n+\t\t\tthrow new NoSuchElementException();\n+\t\t}\n+\t}\n+\n+\tpublic void remove() {\n+\t\tthrow new UnsupportedOperationException();\n+\t}\n+\n+\tprivate class Directory {\n+\t\tfinal File path;\n+\n+\t\tfinal Rules ignoreRules;\n+\n+\t\tDirectory(File path, Rules ignoreRules) {\n+\t\t\tthis.path = path;\n+\t\t\tthis.ignoreRules = ignoreRules;\n+\t\t}\n+\t}\n+\n+}\n\\ No newline at end of file\n-- \n1.5.2.5\n"},{"id":"76528","messageId":"1210424440-13886-11-git-send-email-florianskarten@web.de","threadId":"13461","inReplyTo":"1210424440-13886-1-git-send-email-florianskarten@web.de","subject":"[JGIT PATCH 10/22] Added class FileTreeIterable.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-05-10T13:00:28Z","receivedAt":"2008-05-10T13:00:28Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Signed-off-by: Florian Koeberle <florianskarten@web.de>\n---\n .../jgit/lib/fileiteration/FileTreeIterable.java   |   48 ++++++++++++++++++++\n 1 files changed, 48 insertions(+), 0 deletions(-)\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/FileTreeIterable.java\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/FileTreeIterable.java b/org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/FileTreeIterable.java\nnew file mode 100644\nindex 0000000..6922162\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/FileTreeIterable.java\n@@ -0,0 +1,48 @@\n+/*\n+ *  Copyright (C) 2008 Florian KÃ¶berle\n+ *\n+ *  This library is free software; you can redistribute it and/or\n+ *  modify it under the terms of the GNU General Public\n+ *  License, version 2, as published by the Free Software Foundation.\n+ *\n+ *  This library is distributed in the hope that it will be useful,\n+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+ *  General Public License for more details.\n+ *\n+ *  You should have received a copy of the GNU General Public\n+ *  License along with this library; if not, write to the Free Software\n+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301\n+ */\n+package org.spearce.jgit.lib.fileiteration;\n+\n+import java.io.File;\n+import java.util.Iterator;\n+\n+/**\n+ * Use this class to iterate over some by rules determined files in a project\n+ * directory.\n+ * \n+ * @author Florian KÃ¶berle\n+ * \n+ */\n+class FileTreeIterable implements Iterable<File> {\n+\tprivate final File projectDirectory;\n+\n+\tprivate final Rules ignoreRules;\n+\n+\tprivate final boolean includeRootDirectory;\n+\n+\tFileTreeIterable(File projectDirectory, Rules ignoreRules,\n+\t\t\tboolean includeRootDirectory) {\n+\t\tthis.projectDirectory = projectDirectory;\n+\t\tthis.ignoreRules = ignoreRules;\n+\t\tthis.includeRootDirectory = includeRootDirectory;\n+\t}\n+\n+\tpublic Iterator<File> iterator() {\n+\t\treturn new FileTreeIterator(projectDirectory, ignoreRules,\n+\t\t\t\tincludeRootDirectory);\n+\t}\n+\n+}\n-- \n1.5.2.5\n"},{"id":"76527","messageId":"1210424440-13886-12-git-send-email-florianskarten@web.de","threadId":"13461","inReplyTo":"1210424440-13886-1-git-send-email-florianskarten@web.de","subject":"[JGIT PATCH 11/22] Added the class StarPattern.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-05-10T13:00:29Z","receivedAt":"2008-05-10T13:00:29Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Signed-off-by: Florian Koeberle <florianskarten@web.de>\n---\n .../jgit/lib/fileiteration/StarPattern.java        |   50 ++++++++++++++++++++\n 1 files changed, 50 insertions(+), 0 deletions(-)\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/StarPattern.java\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/StarPattern.java b/org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/StarPattern.java\nnew file mode 100644\nindex 0000000..bd773ef\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/StarPattern.java\n@@ -0,0 +1,50 @@\n+/*\n+ *  Copyright (C) 2008 Florian KÃ¶berle\n+ *\n+ *  This library is free software; you can redistribute it and/or\n+ *  modify it under the terms of the GNU General Public\n+ *  License, version 2, as published by the Free Software Foundation.\n+ *\n+ *  This library is distributed in the hope that it will be useful,\n+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+ *  General Public License for more details.\n+ *\n+ *  You should have received a copy of the GNU General Public\n+ *  License along with this library; if not, write to the Free Software\n+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301\n+ */\n+package org.spearce.jgit.lib.fileiteration;\n+\n+import java.util.regex.Pattern;\n+\n+class StarPattern {\n+\n+\tprivate final Pattern regexPattern;\n+\n+\tprivate final String stringPattern;\n+\n+\tStarPattern(String starPattern) {\n+\t\tif (starPattern.contains(\"*\")) {\n+\t\t\tString regularExpression = starPattern;\n+\t\t\tregularExpression = regularExpression.replace(\".\", \"[.]\");\n+\t\t\tregularExpression = regularExpression.replace(\"*\", \".*\");\n+\t\t\tthis.regexPattern = Pattern.compile(regularExpression);\n+\t\t\tthis.stringPattern = null;\n+\t\t} else {\n+\t\t\tthis.regexPattern = null;\n+\t\t\tthis.stringPattern = starPattern;\n+\t\t}\n+\n+\t}\n+\n+\tboolean matches(String stringToMatch) {\n+\t\tif (regexPattern != null) {\n+\t\t\treturn regexPattern.matcher(stringToMatch).matches();\n+\t\t} else if (stringPattern != null) {\n+\t\t\treturn stringPattern.equals(stringToMatch);\n+\t\t}\n+\t\tthrow new IllegalStateException(\"Oops, this should never happen.\");\n+\t}\n+\n+}\n-- \n1.5.2.5\n"},{"id":"76513","messageId":"1210424440-13886-13-git-send-email-florianskarten@web.de","threadId":"13461","inReplyTo":"1210424440-13886-1-git-send-email-florianskarten@web.de","subject":"[JGIT PATCH 12/22] Added the class GlobalFilePattern","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-05-10T13:00:30Z","receivedAt":"2008-05-10T13:00:30Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Signed-off-by: Florian Koeberle <florianskarten@web.de>\n---\n .../jgit/lib/fileiteration/GlobalFilePattern.java  |   50 ++++++++++++++++++++\n 1 files changed, 50 insertions(+), 0 deletions(-)\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/GlobalFilePattern.java\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/GlobalFilePattern.java b/org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/GlobalFilePattern.java\nnew file mode 100644\nindex 0000000..92b133f\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/GlobalFilePattern.java\n@@ -0,0 +1,50 @@\n+/*\n+ *  Copyright (C) 2008 Florian KÃ¶berle\n+ *\n+ *  This library is free software; you can redistribute it and/or\n+ *  modify it under the terms of the GNU General Public\n+ *  License, version 2, as published by the Free Software Foundation.\n+ *\n+ *  This library is distributed in the hope that it will be useful,\n+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+ *  General Public License for more details.\n+ *\n+ *  You should have received a copy of the GNU General Public\n+ *  License along with this library; if not, write to the Free Software\n+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301\n+ */\n+package org.spearce.jgit.lib.fileiteration;\n+\n+class GlobalFilePattern implements FilePattern {\n+\tprivate final StarPattern starPattern;\n+\n+\tprivate final boolean matchDirectoriesOnly;\n+\n+\tGlobalFilePattern(String starPatternString, boolean matchDirectoriesOnly) {\n+\t\tthis.starPattern = new StarPattern(starPatternString);\n+\t\tthis.matchDirectoriesOnly = matchDirectoriesOnly;\n+\t}\n+\n+\tpublic boolean canMatchAtThisDirectoryLevel() {\n+\t\treturn true;\n+\t}\n+\n+\tpublic FilePattern getPatternForSubDirectory(String directoryName) {\n+\t\tif (match(directoryName, true)) {\n+\t\t\treturn MATCH_ALWAYS;\n+\t\t}\n+\t\treturn this;\n+\t}\n+\n+\tpublic boolean match(String fileName, boolean fileIsDirectory) {\n+\t\tif (matchDirectoriesOnly && !fileIsDirectory) {\n+\t\t\treturn false;\n+\t\t}\n+\t\treturn starPattern.matches(fileName);\n+\t}\n+\n+\tpublic boolean isSameForSubDirectories() {\n+\t\treturn false;\n+\t}\n+}\n-- \n1.5.2.5\n"},{"id":"76514","messageId":"1210424440-13886-14-git-send-email-florianskarten@web.de","threadId":"13461","inReplyTo":"1210424440-13886-1-git-send-email-florianskarten@web.de","subject":"[JGIT PATCH 13/22] Added the class ComplexFilePattern.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-05-10T13:00:31Z","receivedAt":"2008-05-10T13:00:31Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Signed-off-by: Florian Koeberle <florianskarten@web.de>\n---\n .../jgit/lib/fileiteration/ComplexFilePattern.java |   89 ++++++++++++++++++++\n 1 files changed, 89 insertions(+), 0 deletions(-)\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/ComplexFilePattern.java\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/ComplexFilePattern.java b/org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/ComplexFilePattern.java\nnew file mode 100644\nindex 0000000..e658d45\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/ComplexFilePattern.java\n@@ -0,0 +1,89 @@\n+/*\n+ *  Copyright (C) 2008 Florian KÃ¶berle\n+ *\n+ *  This library is free software; you can redistribute it and/or\n+ *  modify it under the terms of the GNU General Public\n+ *  License, version 2, as published by the Free Software Foundation.\n+ *\n+ *  This library is distributed in the hope that it will be useful,\n+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+ *  General Public License for more details.\n+ *\n+ *  You should have received a copy of the GNU General Public\n+ *  License along with this library; if not, write to the Free Software\n+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301\n+ */\n+package org.spearce.jgit.lib.fileiteration;\n+\n+import java.util.List;\n+import java.util.ArrayList;\n+\n+class ComplexFilePattern implements FilePattern {\n+\t/**\n+\t * Can contain String and\n+\t */\n+\tprivate final List<StarPattern> usedPatternList;\n+\n+\tprivate final boolean matchDirectoriesOnly;\n+\n+\tprivate final int offset;\n+\n+\tprivate ComplexFilePattern(List<StarPattern> List,\n+\t\t\tboolean matchDirectoriesOnly, int offset) {\n+\t\tthis.usedPatternList = List;\n+\t\tthis.matchDirectoriesOnly = matchDirectoriesOnly;\n+\t\tthis.offset = offset;\n+\t}\n+\n+\tComplexFilePattern(List<String> patternStrings, boolean matchDirectoriesOnly) {\n+\t\tthis.usedPatternList = new ArrayList<StarPattern>(patternStrings.size());\n+\t\tfor (String patternString : patternStrings) {\n+\t\t\tthis.usedPatternList.add(new StarPattern(patternString));\n+\t\t}\n+\t\tthis.offset = 0;\n+\t\tthis.matchDirectoriesOnly = matchDirectoriesOnly;\n+\t}\n+\n+\tint getActualPathSize() {\n+\t\treturn usedPatternList.size() - offset;\n+\t}\n+\n+\tprivate StarPattern getPatternOfCurrentLevel() {\n+\t\treturn usedPatternList.get(offset);\n+\t}\n+\n+\tpublic boolean canMatchAtThisDirectoryLevel() {\n+\t\treturn getActualPathSize() == 1;\n+\t}\n+\n+\tpublic FilePattern getPatternForSubDirectory(String directoryName) {\n+\n+\t\tif (getActualPathSize() > 1) {\n+\t\t\tif (getPatternOfCurrentLevel().matches(directoryName)) {\n+\t\t\t\treturn new ComplexFilePattern(usedPatternList,\n+\t\t\t\t\t\tmatchDirectoriesOnly, offset + 1);\n+\t\t\t} else {\n+\t\t\t\treturn FilePattern.MATCH_NEVER;\n+\t\t\t}\n+\t\t}\n+\t\tassert (getActualPathSize() == 1);\n+\t\tif (match(directoryName, true)) {\n+\t\t\treturn FilePattern.MATCH_ALWAYS;\n+\t\t} else {\n+\t\t\treturn FilePattern.MATCH_NEVER;\n+\t\t}\n+\t}\n+\n+\tpublic boolean match(String fileName, boolean fileIsDirectory) {\n+\t\tif (!fileIsDirectory && matchDirectoriesOnly) {\n+\t\t\treturn false;\n+\t\t}\n+\t\treturn getPatternOfCurrentLevel().matches(fileName);\n+\t}\n+\n+\tpublic boolean isSameForSubDirectories() {\n+\t\treturn false;\n+\t}\n+\n+}\n-- \n1.5.2.5\n"},{"id":"76511","messageId":"1210424440-13886-15-git-send-email-florianskarten@web.de","threadId":"13461","inReplyTo":"1210424440-13886-1-git-send-email-florianskarten@web.de","subject":"[JGIT PATCH 14/22] Added the class IgnoreRuleListFactory.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-05-10T13:00:32Z","receivedAt":"2008-05-10T13:00:32Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Signed-off-by: Florian Koeberle <florianskarten@web.de>\n---\n .../lib/fileiteration/IgnoreRuleListFactory.java   |  106 ++++++++++++++++++++\n 1 files changed, 106 insertions(+), 0 deletions(-)\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/IgnoreRuleListFactory.java\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/IgnoreRuleListFactory.java b/org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/IgnoreRuleListFactory.java\nnew file mode 100644\nindex 0000000..aaf3aae\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/IgnoreRuleListFactory.java\n@@ -0,0 +1,106 @@\n+/*\n+ *  Copyright (C) 2008 Florian KÃ¶berle\n+ *\n+ *  This library is free software; you can redistribute it and/or\n+ *  modify it under the terms of the GNU General Public\n+ *  License, version 2, as published by the Free Software Foundation.\n+ *\n+ *  This library is distributed in the hope that it will be useful,\n+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+ *  General Public License for more details.\n+ *\n+ *  You should have received a copy of the GNU General Public\n+ *  License along with this library; if not, write to the Free Software\n+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301\n+ */\n+package org.spearce.jgit.lib.fileiteration;\n+\n+import java.io.File;\n+import java.io.FileNotFoundException;\n+import java.util.ArrayList;\n+import java.util.LinkedList;\n+import java.util.List;\n+import java.util.Scanner;\n+import java.util.StringTokenizer;\n+\n+/**\n+ * This class can be used to create lists of {@link Rule} objects from lines of\n+ * .gitignore like files.\n+ * \n+ * @author Florian KÃ¶berle\n+ * \n+ */\n+class IgnoreRuleListFactory {\n+\n+\tList<Rule> createIgnoreRuleList(Iterable<String> lineIterable) {\n+\t\tLinkedList<Rule> rules = new LinkedList<Rule>();\n+\t\tfor (String line : lineIterable) {\n+\t\t\tfinal String trimmedLine = line.trim();\n+\t\t\tif (trimmedLine.startsWith(\"#\")) {\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t\tif (trimmedLine.length() == 0) {\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t\trules.add(0, createRule(trimmedLine));\n+\t\t}\n+\t\treturn rules;\n+\t}\n+\n+\tList<Rule> createIgnoreRuleList(List<File> files)\n+\t\t\tthrows FileNotFoundException {\n+\t\tfinal List<String> lines = new ArrayList<String>();\n+\t\tfor (File file : files) {\n+\t\t\tScanner scanner = new Scanner(file);\n+\t\t\ttry {\n+\t\t\t\twhile (scanner.hasNextLine()) {\n+\t\t\t\t\tlines.add(scanner.nextLine());\n+\t\t\t\t}\n+\t\t\t} finally {\n+\t\t\t\tscanner.close();\n+\t\t\t}\n+\t\t}\n+\t\treturn createIgnoreRuleList(lines);\n+\t}\n+\n+\tprivate Rule createRule(String trimmedLine) {\n+\t\tfinal boolean exclude;\n+\t\tString patternString;\n+\t\tif (trimmedLine.startsWith(\"!\")) {\n+\t\t\texclude = false;\n+\t\t\tpatternString = trimmedLine.substring(1);\n+\t\t} else {\n+\t\t\texclude = true;\n+\t\t\tpatternString = trimmedLine;\n+\t\t}\n+\n+\t\tfinal boolean matchDirectoriesOnly;\n+\t\tif (patternString.endsWith(\"/\")) {\n+\t\t\tmatchDirectoriesOnly = true;\n+\t\t\tpatternString = patternString.substring(0,\n+\t\t\t\t\tpatternString.length() - 1);\n+\t\t} else {\n+\t\t\tmatchDirectoriesOnly = false;\n+\t\t}\n+\n+\t\tfinal FilePattern pattern;\n+\t\tif (patternString.contains(\"/\")) {\n+\t\t\tif (patternString.startsWith(\"/\")) {\n+\t\t\t\tpatternString = patternString.substring(1);\n+\t\t\t}\n+\t\t\tfinal StringTokenizer stringTokenizer = new StringTokenizer(\n+\t\t\t\t\tpatternString, \"/\");\n+\t\t\tfinal List<String> patternList = new ArrayList<String>();\n+\t\t\twhile (stringTokenizer.hasMoreTokens()) {\n+\t\t\t\tfinal String token = stringTokenizer.nextToken();\n+\t\t\t\tpatternList.add(token);\n+\t\t\t}\n+\t\t\tpattern = new ComplexFilePattern(patternList, matchDirectoriesOnly);\n+\t\t} else {\n+\t\t\tpattern = new GlobalFilePattern(patternString, matchDirectoriesOnly);\n+\t\t}\n+\t\treturn new Rule(exclude, pattern);\n+\t}\n+\n+}\n-- \n1.5.2.5\n"},{"id":"76529","messageId":"1210424440-13886-16-git-send-email-florianskarten@web.de","threadId":"13461","inReplyTo":"1210424440-13886-1-git-send-email-florianskarten@web.de","subject":"[JGIT PATCH 15/22] Added a Rules interface implementation and a factory for it.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-05-10T13:00:33Z","receivedAt":"2008-05-10T13:00:33Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Signed-off-by: Florian Koeberle <florianskarten@web.de>\n---\n .../fileiteration/RuleListToObjectConverter.java   |  113 ++++++++++++++++++++\n .../lib/fileiteration/RulesImplementation.java     |   87 +++++++++++++++\n 2 files changed, 200 insertions(+), 0 deletions(-)\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/RuleListToObjectConverter.java\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/RulesImplementation.java\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/RuleListToObjectConverter.java b/org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/RuleListToObjectConverter.java\nnew file mode 100644\nindex 0000000..533a35b\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/RuleListToObjectConverter.java\n@@ -0,0 +1,113 @@\n+/*\n+ *  Copyright (C) 2008 Florian KÃ¶berle\n+ *\n+ *  This library is free software; you can redistribute it and/or\n+ *  modify it under the terms of the GNU General Public\n+ *  License, version 2, as published by the Free Software Foundation.\n+ *\n+ *  This library is distributed in the hope that it will be useful,\n+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+ *  General Public License for more details.\n+ *\n+ *  You should have received a copy of the GNU General Public\n+ *  License along with this library; if not, write to the Free Software\n+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301\n+ */\n+package org.spearce.jgit.lib.fileiteration;\n+\n+import java.util.ArrayList;\n+import java.util.Iterator;\n+import java.util.List;\n+\n+class RuleListToObjectConverter {\n+\tprotected Rules createIgnoreRules(Iterator<Rule> ruleIterator) {\n+\t\tfinal List<Rule> rules = getNessesaryRulesFromIterator(ruleIterator);\n+\t\tremoveUnnecessaryDoNotIgnoreRulesAtTheEndOfTheList(rules);\n+\t\tremoveUnnecessaryIgnoreRulesNearTheEndOfTheList(rules);\n+\n+\t\tif (rules.size() == 1) {\n+\t\t\tfinal Rule rule = rules.get(0);\n+\t\t\tif (rule.getPattern() == FilePattern.MATCH_ALWAYS) {\n+\t\t\t\tif (rule.isIgnoreAtMatch()) {\n+\t\t\t\t\treturn Rules.IGNORE_ALL;\n+\t\t\t\t} else {\n+\t\t\t\t\treturn Rules.IGNORE_NOTHING;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t} else if (rules.isEmpty()) {\n+\t\t\treturn Rules.IGNORE_NOTHING;\n+\t\t}\n+\t\treturn new RulesImplementation(rules, this);\n+\t}\n+\n+\tprivate List<Rule> getNessesaryRulesFromIterator(Iterator<Rule> ruleIterator) {\n+\t\tfinal List<Rule> rules = new ArrayList<Rule>();\n+\t\twhile (ruleIterator.hasNext()) {\n+\t\t\tfinal Rule subRule = ruleIterator.next();\n+\t\t\tif (subRule.getPattern() == FilePattern.MATCH_NEVER) {\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t\trules.add(subRule);\n+\t\t\t// There is no need for rules after a rule witch match always,\n+\t\t\t// as such a rule would never be the first rule which matches.\n+\t\t\tif (subRule.getPattern() == FilePattern.MATCH_ALWAYS) {\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\t\treturn rules;\n+\t}\n+\n+\t/**\n+\t * Expects that\n+\t * {@link #removeUnnecessaryDoNotIgnoreRulesAtTheEndOfTheList(List)} has\n+\t * been executed first.\n+\t * \n+\t * @param rules\n+\t *            rule list to reduce.\n+\t */\n+\tprivate void removeUnnecessaryIgnoreRulesNearTheEndOfTheList(\n+\t\t\tfinal List<Rule> rules) {\n+\t\t// Why the following optimization makes only sense for the end of the\n+\t\t// list:\n+\t\t// If there is a \"ignore all\"- rule,\n+\t\t// then it is located at the end of the list\n+\t\t// See how the list is filled to prove this statement.\n+\t\tif (rules.size() >= 2) {\n+\t\t\tfinal Rule lastRule = rules.get(rules.size() - 1);\n+\t\t\tassert lastRule.isIgnoreAtMatch() : \"Expected that no 'not ignore'-rule is at the end of the list any more\";\n+\t\t\tfinal boolean ignoreAllAtEnd = lastRule.getPattern().equals(\n+\t\t\t\t\tFilePattern.MATCH_ALWAYS);\n+\t\t\tif (ignoreAllAtEnd) {\n+\t\t\t\twhile (rules.size() >= 2) {\n+\t\t\t\t\tfinal int ruleBeforeLastIndex = rules.size() - 2;\n+\t\t\t\t\tfinal Rule ruleBeforeLast = rules.get(ruleBeforeLastIndex);\n+\t\t\t\t\tif (ruleBeforeLast.isIgnoreAtMatch()) {\n+\t\t\t\t\t\trules.remove(ruleBeforeLastIndex);\n+\t\t\t\t\t} else {\n+\t\t\t\t\t\tbreak;\n+\t\t\t\t\t}\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\tprivate void removeUnnecessaryDoNotIgnoreRulesAtTheEndOfTheList(\n+\t\t\tfinal List<Rule> rules) {\n+\t\t// Why it is save to remove \"don't ignore rules\" at the end of the list\n+\t\t// if there is no \"ignore rule\" below a \"don't ignore rule\" then\n+\t\t// the path which haven't match jet will never be ignored:\n+\t\t// -> if another \"don't ignore rule\" match then the patch will not be\n+\t\t// ignored\n+\t\t// -> if no \"don't ignore rule\" match then the path will not be ignored.\n+\t\twhile (!rules.isEmpty()) {\n+\t\t\tfinal int indexOfLastRule = rules.size() - 1;\n+\t\t\tfinal Rule lastRule = rules.get(indexOfLastRule);\n+\t\t\tif (lastRule.isIgnoreAtMatch()) {\n+\t\t\t\tbreak;\n+\t\t\t} else {\n+\t\t\t\trules.remove(indexOfLastRule);\n+\t\t\t}\n+\t\t}\n+\t}\n+}\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/RulesImplementation.java b/org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/RulesImplementation.java\nnew file mode 100644\nindex 0000000..b7bf963\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/RulesImplementation.java\n@@ -0,0 +1,87 @@\n+/*\n+ *  Copyright (C) 2008 Florian KÃ¶berle\n+ *\n+ *  This library is free software; you can redistribute it and/or\n+ *  modify it under the terms of the GNU General Public\n+ *  License, version 2, as published by the Free Software Foundation.\n+ *\n+ *  This library is distributed in the hope that it will be useful,\n+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+ *  General Public License for more details.\n+ *\n+ *  You should have received a copy of the GNU General Public\n+ *  License along with this library; if not, write to the Free Software\n+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301\n+ */\n+package org.spearce.jgit.lib.fileiteration;\n+\n+import java.util.ArrayList;\n+import java.util.Iterator;\n+import java.util.List;\n+\n+class RulesImplementation implements Rules {\n+\t/**\n+\t * Complete list of rules. Note that order is: determining rule first.\n+\t */\n+\tprivate final List<Rule> rulesForTree;\n+\n+\t/**\n+\t * {@link Rule} objects which return true at a call of\n+\t * {@link Rule#canMatchAtThisDirectoryLevel}.\n+\t */\n+\tprivate final List<Rule> rulesForThisLevel;\n+\n+\t/**\n+\t * Factory used to create {@link Rules} for sub directories.\n+\t */\n+\tprivate RuleListToObjectConverter factory;\n+\n+\tRulesImplementation(List<Rule> rules, RuleListToObjectConverter factory) {\n+\t\tthis.rulesForTree = rules;\n+\t\tthis.factory = factory;\n+\t\tthis.rulesForThisLevel = new ArrayList<Rule>();\n+\t\tfor (Rule rule : rules) {\n+\t\t\tif (rule.canMatchAtThisDirectoryLevel()) {\n+\t\t\t\tthis.rulesForThisLevel.add(rule);\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\t/**\n+\t * @see org.spearce.jgit.lib.fileiteration.Rules#toIgnore(java.lang.String,\n+\t *      boolean)\n+\t */\n+\tpublic boolean toIgnore(String fileName, boolean fileIsDirectory) {\n+\t\tfor (Rule rule : rulesForThisLevel) {\n+\t\t\tif (rule.getPattern().match(fileName, fileIsDirectory)) {\n+\t\t\t\treturn rule.isIgnoreAtMatch();\n+\t\t\t}\n+\t\t}\n+\t\treturn false;\n+\t}\n+\n+\t/**\n+\t * @see org.spearce.jgit.lib.fileiteration.Rules#getRulesForSubDirectory(java.lang.String)\n+\t */\n+\tpublic Rules getRulesForSubDirectory(final String directoryName) {\n+\t\tfinal Iterator<Rule> subRuleIterator = new Iterator<Rule>() {\n+\t\t\tfinal Iterator<Rule> ruleIterator = rulesForTree.iterator();\n+\n+\t\t\tpublic boolean hasNext() {\n+\t\t\t\treturn ruleIterator.hasNext();\n+\t\t\t}\n+\n+\t\t\tpublic Rule next() {\n+\t\t\t\treturn ruleIterator.next()\n+\t\t\t\t\t\t.getRuleForSubDirectory(directoryName);\n+\t\t\t}\n+\n+\t\t\tpublic void remove() {\n+\t\t\t\tthrow new UnsupportedOperationException();\n+\t\t\t}\n+\n+\t\t};\n+\t\treturn factory.createIgnoreRules(subRuleIterator);\n+\t}\n+}\n-- \n1.5.2.5\n"},{"id":"76525","messageId":"1210424440-13886-17-git-send-email-florianskarten@web.de","threadId":"13461","inReplyTo":"1210424440-13886-1-git-send-email-florianskarten@web.de","subject":"[JGIT PATCH 16/22] Added test class OverallIgnoreRulestest.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-05-10T13:00:34Z","receivedAt":"2008-05-10T13:00:34Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Signed-off-by: Florian Koeberle <florianskarten@web.de>\n---\n .../lib/fileiteration/OverallIgnoreRulesTest.java  |  373 ++++++++++++++++++++\n 1 files changed, 373 insertions(+), 0 deletions(-)\n create mode 100644 org.spearce.jgit.test/tst/org/spearce/jgit/lib/fileiteration/OverallIgnoreRulesTest.java\n\ndiff --git a/org.spearce.jgit.test/tst/org/spearce/jgit/lib/fileiteration/OverallIgnoreRulesTest.java b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/fileiteration/OverallIgnoreRulesTest.java\nnew file mode 100644\nindex 0000000..feb15d7\n--- /dev/null\n+++ b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/fileiteration/OverallIgnoreRulesTest.java\n@@ -0,0 +1,373 @@\n+/*\n+ *  Copyright (C) 2008 Florian KÃ¶berle\n+ *\n+ *  This library is free software; you can redistribute it and/or\n+ *  modify it under the terms of the GNU General Public\n+ *  License, version 2, as published by the Free Software Foundation.\n+ *\n+ *  This library is distributed in the hope that it will be useful,\n+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+ *  General Public License for more details.\n+ *\n+ *  You should have received a copy of the GNU General Public\n+ *  License along with this library; if not, write to the Free Software\n+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301\n+ */\n+package org.spearce.jgit.lib.fileiteration;\n+\n+import java.util.ArrayList;\n+import java.util.Collections;\n+import java.util.List;\n+\n+import org.spearce.jgit.lib.fileiteration.Rules;\n+\n+import junit.framework.TestCase;\n+\n+public class OverallIgnoreRulesTest extends TestCase {\n+\tprivate IgnoreRulesFactory factory;\n+\n+\t@Override\n+\tprotected void setUp() throws Exception {\n+\t\tfactory = new IgnoreRulesFactory();\n+\t}\n+\n+\tpublic void testSimpleGlobalPattern() {\n+\t\tList<String> lines = new ArrayList<String>();\n+\t\tlines.add(\"ab\");\n+\t\tfinal Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);\n+\t\tassertTrue(ignoreRules.toIgnore(\"ab\", false));\n+\t\tassertTrue(ignoreRules.toIgnore(\"ab\", true));\n+\t\tassertFalse(ignoreRules.toIgnore(\"abc\", false));\n+\t\tassertFalse(ignoreRules.toIgnore(\"abc\", true));\n+\t}\n+\n+\tpublic void testGlobalPatternWithOneStar() {\n+\t\tList<String> lines = new ArrayList<String>();\n+\t\tlines.add(\"a*c\");\n+\t\tfinal Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);\n+\n+\t\tassertTrue(ignoreRules.toIgnore(\"ac\", false));\n+\t\tassertTrue(ignoreRules.toIgnore(\"ac\", true));\n+\n+\t\tassertTrue(ignoreRules.toIgnore(\"abc\", false));\n+\t\tassertTrue(ignoreRules.toIgnore(\"abc\", true));\n+\n+\t\tassertTrue(ignoreRules.toIgnore(\"abbc\", false));\n+\t\tassertTrue(ignoreRules.toIgnore(\"abbc\", true));\n+\n+\t\tassertTrue(ignoreRules.toIgnore(\"aabc\", false));\n+\t\tassertTrue(ignoreRules.toIgnore(\"aabc\", true));\n+\n+\t\tassertFalse(ignoreRules.toIgnore(\"cab\", false));\n+\t\tassertFalse(ignoreRules.toIgnore(\"cab\", true));\n+\t}\n+\n+\tpublic void testGlobalPatternWithTwoStars() {\n+\t\tList<String> lines = new ArrayList<String>();\n+\t\tlines.add(\"a*c*e\");\n+\t\tfinal Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);\n+\n+\t\tassertTrue(ignoreRules.toIgnore(\"ace\", false));\n+\t\tassertTrue(ignoreRules.toIgnore(\"ace\", true));\n+\n+\t\tassertTrue(ignoreRules.toIgnore(\"abcde\", false));\n+\t\tassertTrue(ignoreRules.toIgnore(\"abcde\", true));\n+\n+\t\tassertTrue(ignoreRules.toIgnore(\"aHellocWorlde\", false));\n+\t\tassertTrue(ignoreRules.toIgnore(\"aHellocWorlde\", true));\n+\n+\t\tassertFalse(ignoreRules.toIgnore(\"ae\", false));\n+\t\tassertFalse(ignoreRules.toIgnore(\"ae\", true));\n+\t}\n+\n+\tpublic void testGlobalPatternWithDots() {\n+\t\tList<String> lines = new ArrayList<String>();\n+\t\tlines.add(\"*.tar.gz\");\n+\t\tfinal Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);\n+\n+\t\tassertTrue(ignoreRules.toIgnore(\"test.tar.gz\", false));\n+\t\tassertTrue(ignoreRules.toIgnore(\"test.tar.gz\", true));\n+\n+\t\tassertTrue(ignoreRules.toIgnore(\".tar.gz\", false));\n+\t\tassertTrue(ignoreRules.toIgnore(\".tar.gz\", true));\n+\n+\t\tassertFalse(ignoreRules.toIgnore(\"test\", false));\n+\t\tassertFalse(ignoreRules.toIgnore(\"test\", true));\n+\n+\t\t// test that \".\" isn't handled as \"any character\"\n+\t\tassertFalse(ignoreRules.toIgnore(\".tarogz\", false));\n+\t\tassertFalse(ignoreRules.toIgnore(\".tarogz\", true));\n+\t}\n+\n+\tpublic void testGlobalPatternDirectoryOnlyRule() {\n+\t\tList<String> lines = new ArrayList<String>();\n+\t\tlines.add(\"a/\");\n+\t\tfinal Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);\n+\n+\t\tassertTrue(ignoreRules.toIgnore(\"a\", true));\n+\t\tassertFalse(ignoreRules.toIgnore(\"a\", false));\n+\n+\t\tfinal Rules ignoreRulesA = ignoreRules.getRulesForSubDirectory(\"a\");\n+\t\tassertSame(Rules.IGNORE_ALL, ignoreRulesA);\n+\n+\t\tfinal Rules ignoreRulesB = ignoreRules.getRulesForSubDirectory(\"b\");\n+\t\tassertTrue(ignoreRulesB.toIgnore(\"a\", true));\n+\t\tassertFalse(ignoreRulesB.toIgnore(\"a\", false));\n+\n+\t\tfinal Rules ignoreRulesBA = ignoreRulesB.getRulesForSubDirectory(\"a\");\n+\t\tassertSame(Rules.IGNORE_ALL, ignoreRulesBA);\n+\n+\t}\n+\n+\tpublic void testSimpleFilePathPattern() {\n+\t\tList<String> lines = new ArrayList<String>();\n+\t\tlines.add(\"a/b/c\");\n+\t\tfinal Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);\n+\t\tassertFalse(ignoreRules.toIgnore(\"a\", true));\n+\t\tassertFalse(ignoreRules.toIgnore(\"a\", false));\n+\t\tassertFalse(ignoreRules.toIgnore(\"b\", true));\n+\t\tassertFalse(ignoreRules.toIgnore(\"b\", false));\n+\t\tassertFalse(ignoreRules.toIgnore(\"c\", true));\n+\t\tassertFalse(ignoreRules.toIgnore(\"c\", false));\n+\n+\t\tfinal Rules ignoreRulesA = ignoreRules.getRulesForSubDirectory(\"a\");\n+\t\tassertFalse(ignoreRulesA.toIgnore(\"a\", true));\n+\t\tassertFalse(ignoreRulesA.toIgnore(\"a\", false));\n+\t\tassertFalse(ignoreRulesA.toIgnore(\"b\", true));\n+\t\tassertFalse(ignoreRulesA.toIgnore(\"b\", false));\n+\t\tassertFalse(ignoreRulesA.toIgnore(\"c\", true));\n+\t\tassertFalse(ignoreRulesA.toIgnore(\"c\", false));\n+\n+\t\tfinal Rules ignoreRulesAB = ignoreRulesA.getRulesForSubDirectory(\"b\");\n+\t\tassertFalse(ignoreRulesAB.toIgnore(\"a\", true));\n+\t\tassertFalse(ignoreRulesAB.toIgnore(\"a\", false));\n+\t\tassertFalse(ignoreRulesAB.toIgnore(\"b\", true));\n+\t\tassertFalse(ignoreRulesAB.toIgnore(\"b\", false));\n+\t\tassertTrue(ignoreRulesAB.toIgnore(\"c\", true));\n+\t\tassertTrue(ignoreRulesAB.toIgnore(\"c\", false));\n+\n+\t\tfinal Rules ignoreRulesABA = ignoreRulesAB.getRulesForSubDirectory(\"a\");\n+\t\tassertSame(Rules.IGNORE_NOTHING, ignoreRulesABA);\n+\n+\t\tfinal Rules ignoreRulesABB = ignoreRulesAB.getRulesForSubDirectory(\"b\");\n+\t\tassertSame(Rules.IGNORE_NOTHING, ignoreRulesABB);\n+\n+\t\tfinal Rules ignoreRulesABC = ignoreRulesAB.getRulesForSubDirectory(\"c\");\n+\t\tassertSame(Rules.IGNORE_ALL, ignoreRulesABC);\n+\t}\n+\n+\tpublic void testFilePathPatternDirectoryOnlyRule() {\n+\t\tList<String> lines = new ArrayList<String>();\n+\t\tlines.add(\"a/b/c/\");\n+\t\tfinal Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);\n+\t\tassertFalse(ignoreRules.toIgnore(\"a\", true));\n+\t\tassertFalse(ignoreRules.toIgnore(\"a\", false));\n+\t\tassertFalse(ignoreRules.toIgnore(\"b\", true));\n+\t\tassertFalse(ignoreRules.toIgnore(\"b\", false));\n+\t\tassertFalse(ignoreRules.toIgnore(\"c\", true));\n+\t\tassertFalse(ignoreRules.toIgnore(\"c\", false));\n+\n+\t\tfinal Rules ignoreRulesA = ignoreRules.getRulesForSubDirectory(\"a\");\n+\t\tassertFalse(ignoreRulesA.toIgnore(\"a\", true));\n+\t\tassertFalse(ignoreRulesA.toIgnore(\"a\", false));\n+\t\tassertFalse(ignoreRulesA.toIgnore(\"b\", true));\n+\t\tassertFalse(ignoreRulesA.toIgnore(\"b\", false));\n+\t\tassertFalse(ignoreRulesA.toIgnore(\"c\", true));\n+\t\tassertFalse(ignoreRulesA.toIgnore(\"c\", false));\n+\n+\t\tfinal Rules ignoreRulesAB = ignoreRulesA.getRulesForSubDirectory(\"b\");\n+\t\tassertFalse(ignoreRulesAB.toIgnore(\"a\", true));\n+\t\tassertFalse(ignoreRulesAB.toIgnore(\"a\", false));\n+\t\tassertFalse(ignoreRulesAB.toIgnore(\"b\", true));\n+\t\tassertFalse(ignoreRulesAB.toIgnore(\"b\", false));\n+\t\tassertTrue(ignoreRulesAB.toIgnore(\"c\", true));\n+\t\tassertFalse(ignoreRulesAB.toIgnore(\"c\", false));\n+\n+\t\tfinal Rules ignoreRulesABA = ignoreRulesAB.getRulesForSubDirectory(\"a\");\n+\t\tassertSame(Rules.IGNORE_NOTHING, ignoreRulesABA);\n+\n+\t\tfinal Rules ignoreRulesABB = ignoreRulesAB.getRulesForSubDirectory(\"b\");\n+\t\tassertSame(Rules.IGNORE_NOTHING, ignoreRulesABB);\n+\n+\t\tfinal Rules ignoreRulesABC = ignoreRulesAB.getRulesForSubDirectory(\"c\");\n+\t\tassertSame(Rules.IGNORE_ALL, ignoreRulesABC);\n+\t}\n+\n+\tpublic void testShortPathPattern() {\n+\t\tList<String> lines = new ArrayList<String>();\n+\t\tlines.add(\"/alpha\");\n+\t\tfinal Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);\n+\t\tassertTrue(ignoreRules.toIgnore(\"alpha\", true));\n+\t\tassertTrue(ignoreRules.toIgnore(\"alpha\", false));\n+\n+\t\tfinal Rules ignoreRulesAlpha = ignoreRules\n+\t\t\t\t.getRulesForSubDirectory(\"alpha\");\n+\t\tassertSame(Rules.IGNORE_ALL, ignoreRulesAlpha);\n+\n+\t\tfinal Rules ignoreRulesBeta = ignoreRules\n+\t\t\t\t.getRulesForSubDirectory(\"beta\");\n+\t\tassertSame(Rules.IGNORE_NOTHING, ignoreRulesBeta);\n+\t}\n+\n+\tpublic void testShortDirectoryPathPattern() {\n+\t\tList<String> lines = new ArrayList<String>();\n+\t\tlines.add(\"/alpha/\");\n+\t\tfinal Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);\n+\t\tassertTrue(ignoreRules.toIgnore(\"alpha\", true));\n+\t\tassertFalse(ignoreRules.toIgnore(\"alpha\", false));\n+\n+\t\tfinal Rules ignoreRulesAlpha = ignoreRules\n+\t\t\t\t.getRulesForSubDirectory(\"alpha\");\n+\t\tassertSame(Rules.IGNORE_ALL, ignoreRulesAlpha);\n+\n+\t\tfinal Rules ignoreRulesBeta = ignoreRules\n+\t\t\t\t.getRulesForSubDirectory(\"beta\");\n+\t\tassertSame(Rules.IGNORE_NOTHING, ignoreRulesBeta);\n+\t}\n+\n+\tpublic void testShortPathPatternWithStar() {\n+\t\tList<String> lines = new ArrayList<String>();\n+\t\tlines.add(\"/.*\");\n+\t\tfinal Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);\n+\n+\t\tassertTrue(ignoreRules.toIgnore(\".test\", true));\n+\t\tassertTrue(ignoreRules.toIgnore(\".test\", false));\n+\n+\t\tassertFalse(ignoreRules.toIgnore(\"test\", true));\n+\t\tassertFalse(ignoreRules.toIgnore(\"test\", false));\n+\n+\t\tfinal Rules ignoreRulesDotTest = ignoreRules\n+\t\t\t\t.getRulesForSubDirectory(\".test\");\n+\t\tassertSame(Rules.IGNORE_ALL, ignoreRulesDotTest);\n+\n+\t\tfinal Rules ignoreRulesTest = ignoreRules\n+\t\t\t\t.getRulesForSubDirectory(\"test\");\n+\t\tassertSame(Rules.IGNORE_NOTHING, ignoreRulesTest);\n+\t}\n+\n+\tpublic void testPathPatternWith2Times2Stars() {\n+\t\tfinal List<String> lines = new ArrayList<String>();\n+\t\tlines.add(\"he*wor*d/*.*\");\n+\t\tfinal Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);\n+\n+\t\tassertFalse(ignoreRules.toIgnore(\"hello\", true));\n+\t\tassertFalse(ignoreRules.toIgnore(\"hello\", false));\n+\t\tfinal Rules ignoreRulesHello = ignoreRules\n+\t\t\t\t.getRulesForSubDirectory(\"hello\");\n+\t\tassertSame(Rules.IGNORE_NOTHING, ignoreRulesHello);\n+\n+\t\tassertFalse(ignoreRules.toIgnore(\"helloworld\", true));\n+\t\tassertFalse(ignoreRules.toIgnore(\"helloworld\", false));\n+\t\tfinal Rules ignoreRulesHelloWorld = ignoreRules\n+\t\t\t\t.getRulesForSubDirectory(\"helloworld\");\n+\t\tassertNotSame(Rules.IGNORE_NOTHING, ignoreRulesHelloWorld);\n+\n+\t\tassertTrue(ignoreRulesHelloWorld.toIgnore(\"test.txt\", true));\n+\t\tassertTrue(ignoreRulesHelloWorld.toIgnore(\"test.txt\", false));\n+\n+\t\tassertFalse(ignoreRulesHelloWorld.toIgnore(\"test\", true));\n+\t\tassertFalse(ignoreRulesHelloWorld.toIgnore(\"test\", false));\n+\n+\t\tfinal Rules ignoreRulesTestTxt = ignoreRulesHelloWorld\n+\t\t\t\t.getRulesForSubDirectory(\"test.txt\");\n+\t\tassertSame(Rules.IGNORE_ALL, ignoreRulesTestTxt);\n+\n+\t\tfinal Rules ignoreRulesTest = ignoreRulesHelloWorld\n+\t\t\t\t.getRulesForSubDirectory(\"test\");\n+\t\tassertSame(Rules.IGNORE_NOTHING, ignoreRulesTest);\n+\t}\n+\n+\tpublic void testEmptyIgnoreList() {\n+\t\tfinal List<String> lines = Collections.emptyList();\n+\t\tfinal Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);\n+\t\tassertSame(Rules.IGNORE_NOTHING, ignoreRules);\n+\t}\n+\n+\tpublic void testOnlyOneNegatedIgnore() {\n+\t\tfinal List<String> lines = new ArrayList<String>();\n+\t\tlines.add(\"!a\");\n+\t\tfinal Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);\n+\t\tassertSame(Rules.IGNORE_NOTHING, ignoreRules);\n+\t}\n+\n+\tpublic void testOnlyThreeNegatedIgnores() {\n+\t\tfinal List<String> lines = new ArrayList<String>();\n+\t\tlines.add(\"!a\");\n+\t\tlines.add(\"!a/b/c\");\n+\t\tlines.add(\"!b*\");\n+\t\tfinal Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);\n+\t\tassertSame(Rules.IGNORE_NOTHING, ignoreRules);\n+\t}\n+\n+\tpublic void testNegatedIgnoreCase1() {\n+\t\tfinal List<String> lines = new ArrayList<String>();\n+\t\tlines.add(\"/a\");\n+\t\tlines.add(\"!b\");\n+\t\tfinal Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);\n+\t\tfinal Rules ignoreRulesA = ignoreRules.getRulesForSubDirectory(\"a\");\n+\t\tfinal Rules ignoreRulesAB = ignoreRulesA.getRulesForSubDirectory(\"b\");\n+\t\tfinal Rules ignoreRulesB = ignoreRules.getRulesForSubDirectory(\"b\");\n+\t\tfinal Rules ignoreRulesC = ignoreRules.getRulesForSubDirectory(\"c\");\n+\t\tassertSame(Rules.IGNORE_NOTHING, ignoreRulesB);\n+\t\tassertSame(Rules.IGNORE_NOTHING, ignoreRulesAB);\n+\t\tassertSame(Rules.IGNORE_NOTHING, ignoreRulesC);\n+\t\tassertTrue(ignoreRules.toIgnore(\"a\", true));\n+\t\tassertTrue(ignoreRules.toIgnore(\"a\", false));\n+\t\tassertTrue(ignoreRulesA.toIgnore(\"c\", true));\n+\t\tassertTrue(ignoreRulesA.toIgnore(\"c\", false));\n+\t}\n+\n+\tpublic void testExceptionOfException() {\n+\t\tfinal List<String> lines = new ArrayList<String>();\n+\t\tlines.add(\"*.*\");\n+\t\tlines.add(\"!*.c\");\n+\t\tlines.add(\"a.c\");\n+\t\tfinal Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);\n+\t\tassertTrue(ignoreRules.toIgnore(\"b.txt\", false));\n+\t\tassertTrue(ignoreRules.toIgnore(\"b.txt\", true));\n+\t\tassertTrue(ignoreRules.toIgnore(\"a.c\", false));\n+\t\tassertTrue(ignoreRules.toIgnore(\"a.c\", true));\n+\t\tassertFalse(ignoreRules.toIgnore(\"b.c\", false));\n+\t\tassertFalse(ignoreRules.toIgnore(\"b.c\", true));\n+\t}\n+\n+\tpublic void testComplexCase() {\n+\t\tfinal List<String> lines = new ArrayList<String>();\n+\t\tlines.add(\"*\");\n+\t\tlines.add(\"!/alpha/src\");\n+\t\tlines.add(\"*~\");\n+\t\tfinal Rules ignoreRules = factory.createIgnoreRulesFromLines(lines);\n+\t\tassertTrue(ignoreRules.toIgnore(\"beta\", true));\n+\t\tassertTrue(ignoreRules.toIgnore(\"alpha\", true));\n+\t\tfinal Rules ignoreRulesAlpha = ignoreRules\n+\t\t\t\t.getRulesForSubDirectory(\"alpha\");\n+\t\tfinal Rules ignoreRulesAlphaBin = ignoreRulesAlpha\n+\t\t\t\t.getRulesForSubDirectory(\"bin\");\n+\t\tfinal Rules ignoreRulesAlphaSrc = ignoreRulesAlpha\n+\t\t\t\t.getRulesForSubDirectory(\"src\");\n+\t\tassertSame(Rules.IGNORE_ALL, ignoreRulesAlphaBin);\n+\t\tassertFalse(ignoreRulesAlphaSrc.toIgnore(\"com\", true));\n+\t\tassertFalse(ignoreRulesAlphaSrc.toIgnore(\"b.java\", false));\n+\t\tassertTrue(ignoreRulesAlphaSrc.toIgnore(\"b.java~\", true));\n+\t}\n+\n+\tprivate class IgnoreRulesFactory {\n+\t\tprivate RuleListToObjectConverter converter = new RuleListToObjectConverter();\n+\n+\t\tprivate IgnoreRuleListFactory listFactory = new IgnoreRuleListFactory();\n+\n+\t\t/**\n+\t\t * @param ignoreFileLines\n+\t\t *            the lines of a ignore file like .gitignore.\n+\t\t * @return a immutable IgnoreRules object.\n+\t\t */\n+\t\tpublic Rules createIgnoreRulesFromLines(Iterable<String> ignoreFileLines) {\n+\t\t\tfinal List<Rule> rules = listFactory\n+\t\t\t\t\t.createIgnoreRuleList(ignoreFileLines);\n+\t\t\treturn converter.createIgnoreRules(rules.iterator());\n+\t\t}\n+\n+\t}\n+\n+}\n-- \n1.5.2.5\n"},{"id":"76521","messageId":"1210424440-13886-18-git-send-email-florianskarten@web.de","threadId":"13461","inReplyTo":"1210424440-13886-1-git-send-email-florianskarten@web.de","subject":"[JGIT PATCH 17/22] Added the class TreeFilePattern.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-05-10T13:00:35Z","receivedAt":"2008-05-10T13:00:35Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Signed-off-by: Florian Koeberle <florianskarten@web.de>\n---\n .../jgit/lib/fileiteration/TreeFilePattern.java    |   77 ++++++++++++++++++++\n 1 files changed, 77 insertions(+), 0 deletions(-)\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/TreeFilePattern.java\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/TreeFilePattern.java b/org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/TreeFilePattern.java\nnew file mode 100644\nindex 0000000..371c632\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/TreeFilePattern.java\n@@ -0,0 +1,77 @@\n+/*\n+ *  Copyright (C) 2008 Florian KÃ¶berle\n+ *\n+ *  This library is free software; you can redistribute it and/or\n+ *  modify it under the terms of the GNU General Public\n+ *  License, version 2, as published by the Free Software Foundation.\n+ *\n+ *  This library is distributed in the hope that it will be useful,\n+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+ *  General Public License for more details.\n+ *\n+ *  You should have received a copy of the GNU General Public\n+ *  License along with this library; if not, write to the Free Software\n+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301\n+ */\n+package org.spearce.jgit.lib.fileiteration;\n+\n+import java.util.List;\n+\n+/**\n+ * Represents a pattern like \"documents/*.txt\" which matches all *.txt files in\n+ * the tree documents.\n+ * \n+ * @author Florian KÃ¶berle\n+ * \n+ */\n+class TreeFilePattern implements FilePattern {\n+\n+\tprivate final List<String> path;\n+\n+\tprivate final int offset;\n+\n+\tprivate final GlobalFilePattern globalFilePattern;\n+\n+\tpublic boolean canMatchAtThisDirectoryLevel() {\n+\t\treturn false;\n+\t}\n+\n+\tTreeFilePattern(List<String> path, GlobalFilePattern globalFilePattern) {\n+\t\tthis.path = path;\n+\t\tthis.offset = 0;\n+\t\tthis.globalFilePattern = globalFilePattern;\n+\t}\n+\n+\tprivate TreeFilePattern(List<String> path, int offset,\n+\t\t\tGlobalFilePattern globalFilePattern) {\n+\t\tthis.path = path;\n+\t\tthis.offset = offset;\n+\t\tthis.globalFilePattern = globalFilePattern;\n+\t}\n+\n+\tpublic FilePattern getPatternForSubDirectory(String directoryName) {\n+\t\ttry {\n+\t\t\tif (!path.get(offset).equals(directoryName)) {\n+\t\t\t\treturn FilePattern.MATCH_NEVER;\n+\t\t\t}\n+\t\t} catch (IndexOutOfBoundsException e) {\n+\t\t\tthrow new IllegalStateException(\n+\t\t\t\t\t\"The offset of this class doesn't refer to a valid position in path\");\n+\t\t}\n+\t\tif (offset == path.size() - 1) {\n+\t\t\treturn globalFilePattern;\n+\t\t} else {\n+\t\t\treturn new TreeFilePattern(path, offset + 1, globalFilePattern);\n+\t\t}\n+\t}\n+\n+\tpublic boolean isSameForSubDirectories() {\n+\t\treturn false;\n+\t}\n+\n+\tpublic boolean match(String fileName, boolean fileIsDirectory) {\n+\t\treturn false;\n+\t}\n+\n+}\n-- \n1.5.2.5\n"},{"id":"76523","messageId":"1210424440-13886-19-git-send-email-florianskarten@web.de","threadId":"13461","inReplyTo":"1210424440-13886-1-git-send-email-florianskarten@web.de","subject":"[JGIT PATCH 18/22] Added InvalidPatternException and PathNotInProjectDirectoryException","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-05-10T13:00:36Z","receivedAt":"2008-05-10T13:00:36Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Signed-off-by: Florian Koeberle <florianskarten@web.de>\n---\n .../jgit/errors/InvalidPatternException.java       |   48 ++++++++++++++++++++\n .../errors/PathNotInProjectDirectoryException.java |   28 +++++++++++\n 2 files changed, 76 insertions(+), 0 deletions(-)\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/errors/InvalidPatternException.java\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/errors/PathNotInProjectDirectoryException.java\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/errors/InvalidPatternException.java b/org.spearce.jgit/src/org/spearce/jgit/errors/InvalidPatternException.java\nnew file mode 100644\nindex 0000000..8cd2a31\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/errors/InvalidPatternException.java\n@@ -0,0 +1,48 @@\n+/*\n+ *  Copyright (C) 2008 Florian KÃ¶berle\n+ *\n+ *  This library is free software; you can redistribute it and/or\n+ *  modify it under the terms of the GNU General Public\n+ *  License, version 2, as published by the Free Software Foundation.\n+ *\n+ *  This library is distributed in the hope that it will be useful,\n+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+ *  General Public License for more details.\n+ *\n+ *  You should have received a copy of the GNU General Public\n+ *  License along with this library; if not, write to the Free Software\n+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301\n+ */\n+package org.spearce.jgit.errors;\n+\n+/**\n+ * Thrown when a pattern passed in an argument was wrong.\n+ * \n+ * @author Florian Koeberle\n+ * \n+ */\n+public class InvalidPatternException extends Exception {\n+\tprivate static final long serialVersionUID = -606889225458579931L;\n+\n+\tprivate final String pattern;\n+\n+\t/**\n+\t * @param message\n+\t *            explains what was wrong with the pattern.\n+\t * @param pattern\n+\t *            the invalid pattern.\n+\t */\n+\tpublic InvalidPatternException(String message, String pattern) {\n+\t\tsuper(message);\n+\t\tthis.pattern = pattern;\n+\t}\n+\n+\t/**\n+\t * @return the invalid pattern.\n+\t */\n+\tpublic String getPattern() {\n+\t\treturn pattern;\n+\t}\n+\n+}\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/errors/PathNotInProjectDirectoryException.java b/org.spearce.jgit/src/org/spearce/jgit/errors/PathNotInProjectDirectoryException.java\nnew file mode 100644\nindex 0000000..1b7b903\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/errors/PathNotInProjectDirectoryException.java\n@@ -0,0 +1,28 @@\n+/*\n+ *  Copyright (C) 2008 Florian KÃ¶berle\n+ *\n+ *  This library is free software; you can redistribute it and/or\n+ *  modify it under the terms of the GNU General Public\n+ *  License, version 2, as published by the Free Software Foundation.\n+ *\n+ *  This library is distributed in the hope that it will be useful,\n+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+ *  General Public License for more details.\n+ *\n+ *  You should have received a copy of the GNU General Public\n+ *  License along with this library; if not, write to the Free Software\n+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301\n+ */\n+package org.spearce.jgit.errors;\n+\n+/**\n+ * Thrown when a path wasn't in the project directory, but expected to be.\n+ * \n+ * @author Florian KÃ¶berle\n+ * \n+ */\n+public class PathNotInProjectDirectoryException extends\n+\t\tIllegalArgumentException {\n+\tprivate static final long serialVersionUID = 1650325142579844202L;\n+}\n-- \n1.5.2.5\n"},{"id":"76524","messageId":"1210424440-13886-20-git-send-email-florianskarten@web.de","threadId":"13461","inReplyTo":"1210424440-13886-1-git-send-email-florianskarten@web.de","subject":"[JGIT PATCH 19/22] Added the class AddRuleListFactory.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-05-10T13:00:37Z","receivedAt":"2008-05-10T13:00:37Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Signed-off-by: Florian Koeberle <florianskarten@web.de>\n---\n .../jgit/lib/fileiteration/AddRuleListFactory.java |  128 ++++++++++++++++++++\n 1 files changed, 128 insertions(+), 0 deletions(-)\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/AddRuleListFactory.java\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/AddRuleListFactory.java b/org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/AddRuleListFactory.java\nnew file mode 100644\nindex 0000000..9d2f942\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/AddRuleListFactory.java\n@@ -0,0 +1,128 @@\n+/*\n+ *  Copyright (C) 2008 Florian KÃ¶berle\n+ *\n+ *  This library is free software; you can redistribute it and/or\n+ *  modify it under the terms of the GNU General Public\n+ *  License, version 2, as published by the Free Software Foundation.\n+ *\n+ *  This library is distributed in the hope that it will be useful,\n+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+ *  General Public License for more details.\n+ *\n+ *  You should have received a copy of the GNU General Public\n+ *  License along with this library; if not, write to the Free Software\n+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301\n+ */\n+package org.spearce.jgit.lib.fileiteration;\n+\n+import java.io.File;\n+import java.io.IOException;\n+import java.util.ArrayList;\n+import java.util.Arrays;\n+import java.util.LinkedList;\n+import java.util.List;\n+\n+import org.spearce.jgit.errors.InvalidPatternException;\n+import org.spearce.jgit.errors.PathNotInProjectDirectoryException;\n+\n+class AddRuleListFactory {\n+\t/*\n+\t * The add command of git 1.5.2.5 behaves a little bit stange: \"git add\n+\t * a/\\*z\" adds the file \"a/b/xyz\" but \"git add a/x\\*\" does not.\n+\t * \n+\t * The first is parsed as pattern \"*z\" for whole directory tree \"a\". The\n+\t * second is parsed as an path.\n+\t * \n+\t */\n+\n+\tprivate static List<String> getRelativePath(File projectDirectory, File file)\n+\t\t\tthrows PathNotInProjectDirectoryException, IOException {\n+\t\tFile currentFile = file.getCanonicalFile();\n+\t\tfinal LinkedList<String> relativePath = new LinkedList<String>();\n+\t\twhile (!currentFile.equals(projectDirectory)) {\n+\t\t\trelativePath.addFirst(currentFile.getName());\n+\t\t\tcurrentFile = currentFile.getParentFile();\n+\t\t\tif (currentFile == null) {\n+\t\t\t\tthrow new PathNotInProjectDirectoryException();\n+\t\t\t}\n+\t\t}\n+\t\treturn relativePath;\n+\t}\n+\n+\tList<Rule> createRuleList(File projectDirectory, File workingDirectory,\n+\t\t\tList<String> filePatternsOfAddCommand)\n+\t\t\tthrows InvalidPatternException, PathNotInProjectDirectoryException,\n+\t\t\tIOException {\n+\n+\t\tfinal List<String> pathPrefix = getRelativePath(projectDirectory,\n+\t\t\t\tworkingDirectory);\n+\n+\t\tfinal List<Rule> ruleList = new ArrayList<Rule>(\n+\t\t\t\tfilePatternsOfAddCommand.size());\n+\t\tfor (String pattern : filePatternsOfAddCommand) {\n+\t\t\tfinal boolean matchDirectoriesOnly;\n+\t\t\tif (pattern.endsWith(File.separator)) {\n+\t\t\t\tpattern = pattern.substring(0, pattern.length() - 1);\n+\t\t\t\tmatchDirectoriesOnly = true;\n+\t\t\t} else {\n+\t\t\t\tmatchDirectoriesOnly = false;\n+\t\t\t}\n+\n+\t\t\tfinal String[] relativePath = pattern.split(\"[\" + File.separator\n+\t\t\t\t\t+ \"]\");\n+\t\t\tfinal List<String> path = new ArrayList<String>();\n+\t\t\tpath.addAll(pathPrefix);\n+\t\t\tpath.addAll(Arrays.asList(relativePath));\n+\t\t\tassert (!path.isEmpty());\n+\n+\t\t\tfinal FilePattern filePattern = createFilePattern(pattern,\n+\t\t\t\t\tmatchDirectoriesOnly, path);\n+\t\t\tfinal Rule rule = new Rule(false, filePattern);\n+\t\t\truleList.add(rule);\n+\n+\t\t}\n+\t\treturn ruleList;\n+\t}\n+\n+\tprivate static FilePattern createFilePattern(String pattern,\n+\t\t\tboolean matchDirectoriesOnly, List<String> path)\n+\t\t\tthrows InvalidPatternException {\n+\t\t/*\n+\t\t * I did several tests with the git-add command, and it seems that it\n+\t\t * handles a pattern as a fileGlob, if it has only one star at the\n+\t\t * beginning of the latest part of the path. Otherwise it handle it as\n+\t\t * file pattern.\n+\t\t */\n+\n+\t\tfinal String lastPathElement = path.get(path.size() - 1);\n+\t\tfinal boolean isFileGlob = lastPathElement.startsWith(\"*\");\n+\t\tfinal FilePattern filePattern;\n+\t\tif (isFileGlob) {\n+\t\t\tfilePattern = createGlobalOrTreeFilePattern(matchDirectoriesOnly,\n+\t\t\t\t\tpath, lastPathElement);\n+\t\t} else {\n+\t\t\tfor (String pathElement : path) {\n+\t\t\t\tif (pathElement.contains(\"*\")) {\n+\t\t\t\t\tthrow new InvalidPatternException(\n+\t\t\t\t\t\t\t\"Stars are not allowed here\", pattern);\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\tfilePattern = new ComplexFilePattern(path, matchDirectoriesOnly);\n+\t\t}\n+\t\treturn filePattern;\n+\t}\n+\n+\tprivate static FilePattern createGlobalOrTreeFilePattern(\n+\t\t\tfinal boolean matchDirectoriesOnly, final List<String> path,\n+\t\t\tfinal String lastPathElement) {\n+\t\tfinal GlobalFilePattern globalFilePatternForTree = new GlobalFilePattern(\n+\t\t\t\tlastPathElement, matchDirectoriesOnly);\n+\t\tfinal List<String> targetTree = path.subList(0, path.size() - 1);\n+\t\tif (targetTree.isEmpty()) {\n+\t\t\treturn globalFilePatternForTree;\n+\t\t} else {\n+\t\t\treturn new TreeFilePattern(targetTree, globalFilePatternForTree);\n+\t\t}\n+\t}\n+}\n-- \n1.5.2.5\n"},{"id":"76520","messageId":"1210424440-13886-21-git-send-email-florianskarten@web.de","threadId":"13461","inReplyTo":"1210424440-13886-1-git-send-email-florianskarten@web.de","subject":"[JGIT PATCH 20/22] Added class FileIterableFactoryForAddCommand.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-05-10T13:00:38Z","receivedAt":"2008-05-10T13:00:38Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Signed-off-by: Florian Koeberle <florianskarten@web.de>\n---\n .../FileIterableFactoryForAddCommand.java          |  118 ++++++++++++++++++++\n 1 files changed, 118 insertions(+), 0 deletions(-)\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/FileIterableFactoryForAddCommand.java\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/FileIterableFactoryForAddCommand.java b/org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/FileIterableFactoryForAddCommand.java\nnew file mode 100644\nindex 0000000..4674a87\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/fileiteration/FileIterableFactoryForAddCommand.java\n@@ -0,0 +1,118 @@\n+/*\n+ *  Copyright (C) 2008 Florian KÃ¶berle\n+ *\n+ *  This library is free software; you can redistribute it and/or\n+ *  modify it under the terms of the GNU General Public\n+ *  License, version 2, as published by the Free Software Foundation.\n+ *\n+ *  This library is distributed in the hope that it will be useful,\n+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+ *  General Public License for more details.\n+ *\n+ *  You should have received a copy of the GNU General Public\n+ *  License along with this library; if not, write to the Free Software\n+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301\n+ */\n+package org.spearce.jgit.lib.fileiteration;\n+\n+import java.io.File;\n+import java.io.FileNotFoundException;\n+import java.io.IOException;\n+import java.util.ArrayList;\n+import java.util.Arrays;\n+import java.util.List;\n+\n+import org.spearce.jgit.errors.InvalidPatternException;\n+import org.spearce.jgit.errors.PathNotInProjectDirectoryException;\n+import org.spearce.jgit.lib.GitPathConstants;\n+import org.spearce.jgit.lib.Project;\n+\n+/**\n+ * This class is designed to serve the needs of someone who want to implement a\n+ * git-add command and needs to determine the files to add.\n+ * \n+ * @author Florian KÃ¶berle\n+ * \n+ */\n+public class FileIterableFactoryForAddCommand {\n+\tprivate final RuleListToObjectConverter converter = new RuleListToObjectConverter();\n+\n+\tprivate final IgnoreRuleListFactory ignoreRuleListFactory = new IgnoreRuleListFactory();\n+\n+\tprivate final AddRuleListFactory addRuleListFactory = new AddRuleListFactory();\n+\n+\t/**\n+\t * @param project\n+\t *            a git project.\n+\t * @param projectSubDirectory\n+\t *            a directory in the projectDirectory.\n+\t * @param filePatternsOfAddCommand\n+\t *            determines the files to iterate over.\n+\t * @return an {@link Iterable} which can be used to iterate over all\n+\t *         matching files in the project directory which are not ignored by\n+\t *         some ignore rules.\n+\t * @throws InvalidPatternException\n+\t * @throws IOException\n+\t *             for some reasons.\n+\t * @throws PathNotInProjectDirectoryException\n+\t *             if projectSubDirectory isn't a subdirectory of the project\n+\t *             directory.\n+\t */\n+\tpublic Iterable<File> createFileTreeIterable(Project project,\n+\t\t\tFile projectSubDirectory, List<String> filePatternsOfAddCommand)\n+\t\t\tthrows InvalidPatternException, PathNotInProjectDirectoryException,\n+\t\t\tIOException {\n+\t\tfinal File gitDirectory = project.getRepository().getDirectory();\n+\t\tfinal Rules rules = createRules(project.getDirectory(), gitDirectory,\n+\t\t\t\tprojectSubDirectory, filePatternsOfAddCommand);\n+\t\treturn new FileTreeIterable(project.getDirectory(), rules, false);\n+\t}\n+\n+\tprivate Rules createRules(File projectDirectory, File gitDirectory,\n+\t\t\tFile workingDirectory, List<String> filePatternsOfAddCommand)\n+\t\t\tthrows InvalidPatternException, PathNotInProjectDirectoryException,\n+\t\t\tIOException {\n+\t\tfinal Rule gitDirectoryIgnoreRule = createGitDirectoryIgnoreRule();\n+\t\tfinal List<Rule> ignoreRuleListFromFiles = createExcludeRules(\n+\t\t\t\tprojectDirectory, gitDirectory);\n+\t\tfinal List<Rule> includeRules = addRuleListFactory.createRuleList(\n+\t\t\t\tprojectDirectory, workingDirectory, filePatternsOfAddCommand);\n+\t\tfinal List<Rule> ruleList = new ArrayList<Rule>();\n+\n+\t\truleList.add(gitDirectoryIgnoreRule);\n+\t\truleList.addAll(ignoreRuleListFromFiles);\n+\t\truleList.addAll(includeRules);\n+\t\truleList.add(new Rule(true, FilePattern.MATCH_ALWAYS));\n+\n+\t\treturn converter.createIgnoreRules(ruleList.iterator());\n+\t}\n+\n+\tprivate List<Rule> createExcludeRules(File projectDirectory,\n+\t\t\tFile gitDirectory) {\n+\t\tfinal List<File> possibleIgnoreFiles = new ArrayList<File>(2);\n+\t\tpossibleIgnoreFiles.add(new File(projectDirectory, \".gitignore\"));\n+\t\tpossibleIgnoreFiles.add(new File(new File(gitDirectory, \"info\"),\n+\t\t\t\t\"exclude\"));\n+\n+\t\tfinal List<File> ignoreFiles = new ArrayList<File>();\n+\t\tfor (File possibleIgnoreFile : possibleIgnoreFiles) {\n+\t\t\tif (possibleIgnoreFile.isFile()) {\n+\t\t\t\tignoreFiles.add(possibleIgnoreFile);\n+\t\t\t}\n+\t\t}\n+\n+\t\ttry {\n+\t\t\treturn ignoreRuleListFactory.createIgnoreRuleList(ignoreFiles);\n+\t\t} catch (FileNotFoundException e) {\n+\t\t\tthrow new RuntimeException(\"unexpected removal of ignore files\", e);\n+\t\t}\n+\t}\n+\n+\tprivate Rule createGitDirectoryIgnoreRule() {\n+\t\tfinal FilePattern gitDirectoryPattern = new ComplexFilePattern(Arrays\n+\t\t\t\t.asList(GitPathConstants.REPOSITORY_DIRECTORY_NAME), true);\n+\t\tfinal Rule gitDirectoryIgnoreRule = new Rule(true, gitDirectoryPattern);\n+\t\treturn gitDirectoryIgnoreRule;\n+\t}\n+}\n-- \n1.5.2.5\n"},{"id":"76526","messageId":"1210424440-13886-22-git-send-email-florianskarten@web.de","threadId":"13461","inReplyTo":"1210424440-13886-1-git-send-email-florianskarten@web.de","subject":"[JGIT PATCH 21/22] Added test class FileIterableFactoryForAddCommandTest.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-05-10T13:00:39Z","receivedAt":"2008-05-10T13:00:39Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"Signed-off-by: Florian Koeberle <florianskarten@web.de>\n---\n .../FileIterableFactoryForAddCommandTest.java      |  310 ++++++++++++++++++++\n 1 files changed, 310 insertions(+), 0 deletions(-)\n create mode 100644 org.spearce.jgit.test/tst/org/spearce/jgit/lib/fileiteration/FileIterableFactoryForAddCommandTest.java\n\ndiff --git a/org.spearce.jgit.test/tst/org/spearce/jgit/lib/fileiteration/FileIterableFactoryForAddCommandTest.java b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/fileiteration/FileIterableFactoryForAddCommandTest.java\nnew file mode 100644\nindex 0000000..d3c78f4\n--- /dev/null\n+++ b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/fileiteration/FileIterableFactoryForAddCommandTest.java\n@@ -0,0 +1,310 @@\n+/*\n+ *  Copyright (C) 2008 Florian KÃ¶berle\n+ *\n+ *  This library is free software; you can redistribute it and/or\n+ *  modify it under the terms of the GNU General Public\n+ *  License, version 2, as published by the Free Software Foundation.\n+ *\n+ *  This library is distributed in the hope that it will be useful,\n+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+ *  General Public License for more details.\n+ *\n+ *  You should have received a copy of the GNU General Public\n+ *  License along with this library; if not, write to the Free Software\n+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301\n+ */\n+package org.spearce.jgit.lib.fileiteration;\n+\n+import java.io.File;\n+import java.io.IOException;\n+import java.io.PrintWriter;\n+import java.util.ArrayList;\n+import java.util.Arrays;\n+import java.util.Collections;\n+import java.util.HashSet;\n+import java.util.Iterator;\n+import java.util.List;\n+import java.util.NoSuchElementException;\n+import java.util.Set;\n+\n+import junit.framework.TestCase;\n+\n+import org.spearce.jgit.lib.Project;\n+import org.spearce.jgit.lib.ProjectFactory;\n+\n+public class FileIterableFactoryForAddCommandTest extends TestCase {\n+\n+\tprivate Project project;\n+\n+\tprivate FileIterableFactoryForAddCommand factory;\n+\n+\t@Override\n+\tprotected void setUp() throws Exception {\n+\t\tfinal ProjectFactory projectFactory = new ProjectFactory();\n+\t\tfinal File projectDirectory = File.createTempFile(\"test\", \"\");\n+\t\tprojectDirectory.delete();\n+\t\tprojectDirectory.mkdir();\n+\t\tprojectDirectory.deleteOnExit();\n+\t\tthis.project = projectFactory.createProject(projectDirectory);\n+\t\tthis.factory = new FileIterableFactoryForAddCommand();\n+\t}\n+\n+\tpublic void testNoPattern() throws Exception {\n+\t\tcreateFile(\"a.txt\");\n+\t\tfinal Iterable<File> iterable = factory.createFileTreeIterable(project,\n+\t\t\t\tproject.getDirectory(), Collections.<String> emptyList());\n+\t\tfinal Set<File> expectedPathes = Collections.emptySet();\n+\t\tassertIsValidIterable(iterable);\n+\t\tassertIterableReturnsSet(expectedPathes, iterable);\n+\t}\n+\n+\tpublic void testTreePattern1() throws Exception {\n+\t\tfinal Set<File> expectedFiles = new HashSet<File>();\n+\t\tcreateFile(\"a.txt\");\n+\t\texpectedFiles.add(createFile(\"a\", \"a.txt\"));\n+\t\texpectedFiles.add(createFile(\"a\", \"a\", \"a.txt\"));\n+\t\texpectedFiles.add(createFile(\"a\", \"b\", \"a.txt\"));\n+\t\tcreateFile(\"a\", \"b\", \"a.c\");\n+\n+\t\tfinal File directoryA = new File(project.getDirectory(), \"a\");\n+\n+\t\tfinal Iterable<File> iterable = factory.createFileTreeIterable(project,\n+\t\t\t\tdirectoryA, Arrays.asList(\"*.txt\"));\n+\t\tassertIsValidIterable(iterable);\n+\t\tassertIterableReturnsSet(expectedFiles, iterable);\n+\t}\n+\n+\tpublic void testTreePattern2() throws Exception {\n+\t\tfinal Set<File> expectedFiles = new HashSet<File>();\n+\t\tcreateFile(\"a.txt\");\n+\t\texpectedFiles.add(createFile(\"a\", \"a.txt\"));\n+\t\texpectedFiles.add(createFile(\"a\", \"a\", \"a.txt\"));\n+\t\texpectedFiles.add(createFile(\"a\", \"b\", \"a.txt\"));\n+\t\tcreateFile(\"a\", \"b\", \"a.c\");\n+\n+\t\tfinal Iterable<File> iterable = factory.createFileTreeIterable(project,\n+\t\t\t\tproject.getDirectory(), Arrays.asList(\"a\" + File.separator\n+\t\t\t\t\t\t+ \"*.txt\"));\n+\t\tassertIsValidIterable(iterable);\n+\t\tassertIterableReturnsSet(expectedFiles, iterable);\n+\t}\n+\n+\tpublic void testSelectCompleteSubdirectory() throws Exception {\n+\t\tfinal Set<File> expectedPathes = new HashSet<File>();\n+\t\tfinal File directoryA = new File(project.getDirectory(), \"a\");\n+\t\tfinal File directoryAA = new File(directoryA, \"a\");\n+\t\tfinal File directoryAB = new File(directoryA, \"b\");\n+\t\tcreateFile(\"a.txt\");\n+\t\texpectedPathes.add(directoryA);\n+\t\texpectedPathes.add(directoryAA);\n+\t\texpectedPathes.add(createFile(\"a\", \"a.txt\"));\n+\t\texpectedPathes.add(createFile(\"a\", \"a\", \"a.txt\"));\n+\t\texpectedPathes.add(directoryAB);\n+\t\texpectedPathes.add(createFile(\"a\", \"b\", \"a.txt\"));\n+\t\texpectedPathes.add(createFile(\"a\", \"b\", \"a.c\"));\n+\n+\t\tfinal Iterable<File> iterable = factory.createFileTreeIterable(project,\n+\t\t\t\tproject.getDirectory(), Arrays.asList(\"a\"));\n+\n+\t\tassertIsValidIterable(iterable);\n+\t\tassertIterableReturnsSet(expectedPathes, iterable);\n+\t}\n+\n+\tpublic void testSelectTwoSubdirectories() throws Exception {\n+\t\tfinal Set<File> expectedPathes = new HashSet<File>();\n+\t\tfinal File directoryA = new File(project.getDirectory(), \"a\");\n+\t\tfinal File directoryAA = new File(directoryA, \"a\");\n+\t\tfinal File directoryAB = new File(directoryA, \"b\");\n+\t\tcreateFile(\"a.txt\");\n+\t\tcreateFile(\"a\", \"a.txt\");\n+\t\texpectedPathes.add(directoryAA);\n+\t\texpectedPathes.add(createFile(\"a\", \"a\", \"a.txt\"));\n+\t\texpectedPathes.add(directoryAB);\n+\t\texpectedPathes.add(createFile(\"a\", \"b\", \"a.txt\"));\n+\t\texpectedPathes.add(createFile(\"a\", \"b\", \"a.c\"));\n+\n+\t\tfinal List<String> patternList = new ArrayList<String>(2);\n+\t\tpatternList.add(\"a\" + File.separator + \"a\");\n+\t\tpatternList.add(\"a\" + File.separator + \"b\");\n+\t\tfinal Iterable<File> iterable = factory.createFileTreeIterable(project,\n+\t\t\t\tproject.getDirectory(), patternList);\n+\n+\t\tassertIsValidIterable(iterable);\n+\t\tassertIterableReturnsSet(expectedPathes, iterable);\n+\t}\n+\n+\tpublic void testTwoDifferentSelects() throws Exception {\n+\t\tfinal Set<File> expectedPathes = new HashSet<File>();\n+\t\tfinal File directoryA = new File(project.getDirectory(), \"a\");\n+\t\tfinal File directoryAA = new File(directoryA, \"a\");\n+\t\tcreateFile(\"a.txt\");\n+\t\tcreateFile(\"a\", \"a.txt\");\n+\t\texpectedPathes.add(directoryAA);\n+\t\texpectedPathes.add(createFile(\"a\", \"a\", \"a.txt\"));\n+\t\texpectedPathes.add(createFile(\"a\", \"b\", \"a.txt\"));\n+\t\texpectedPathes.add(createFile(\"a\", \"b\", \"c\", \"a.txt\"));\n+\t\tcreateFile(\"a\", \"b\", \"a.c\");\n+\n+\t\tfinal List<String> patternList = new ArrayList<String>(2);\n+\t\tpatternList.add(\"a\" + File.separator + \"a\");\n+\t\tpatternList.add(\"a\" + File.separator + \"b\" + File.separator + \"*.txt\");\n+\n+\t\tfinal Iterable<File> iterable = factory.createFileTreeIterable(project,\n+\t\t\t\tproject.getDirectory(), patternList);\n+\n+\t\tassertIsValidIterable(iterable);\n+\t\tassertIterableReturnsSet(expectedPathes, iterable);\n+\t}\n+\n+\tpublic void testRealisticExample() throws Exception {\n+\t\tfinal Set<File> expectedPathes = new HashSet<File>();\n+\n+\t\t// write the .gitignore file\n+\t\tfinal File dotGitIgnoreFile = createFile(\".gitignore\");\n+\t\tfinal PrintWriter dotGitIgnoreFilePrinter = new PrintWriter(\n+\t\t\t\tdotGitIgnoreFile);\n+\t\ttry {\n+\t\t\tdotGitIgnoreFilePrinter.println(\"/alpha/config.xml\");\n+\t\t\tdotGitIgnoreFilePrinter.println(\"*.class\");\n+\t\t\tdotGitIgnoreFilePrinter.println(\"!/alpha/test/ressources/\");\n+\t\t\tdotGitIgnoreFilePrinter.println(\"*~\");\n+\t\t} finally {\n+\t\t\tdotGitIgnoreFilePrinter.close();\n+\t\t}\n+\n+\t\t// write the .git/info/exclude file\n+\t\tfinal File repositoryDirectory = project.getRepository().getDirectory();\n+\t\tfinal File infoDirectory = new File(repositoryDirectory, \"info\");\n+\t\tinfoDirectory.mkdir();\n+\t\tfinal File infoExcludeFile = new File(infoDirectory, \"exclude\");\n+\t\tfinal PrintWriter infoExcludeFilePrinter = new PrintWriter(\n+\t\t\t\tinfoExcludeFile);\n+\t\ttry {\n+\t\t\tinfoExcludeFilePrinter.println(\"/alpha/test/ressources/mytest.txt\");\n+\t\t} finally {\n+\t\t\tinfoExcludeFilePrinter.close();\n+\t\t}\n+\n+\t\tcreateFile(\"alpha\", \"config.xml\");\n+\t\texpectedPathes.add(createFile(\"alpha\", \"src\", \"Main.java\"));\n+\t\tcreateFile(\"alpha\", \"src\", \"Main.class\");\n+\t\texpectedPathes.add(createFile(\"alpha\", \"test\", \"ressources\",\n+\t\t\t\t\"Example.class\"));\n+\t\texpectedPathes.add(createFile(\"alpha\", \"test\", \"ressources\",\n+\t\t\t\t\"input.txt\"));\n+\t\tcreateFile(\"alpha\", \"test\", \"ressources\", \"input.txt~\");\n+\t\tcreateFile(\"alpha\", \"test\", \"ressources\", \"mytest.txt\");\n+\n+\t\tfinal File alphaDirectory = new File(project.getDirectory(), \"alpha\");\n+\t\tfinal File srcDirectory = new File(alphaDirectory, \"src\");\n+\t\tfinal File testDirectory = new File(alphaDirectory, \"test\");\n+\t\tfinal File ressources = new File(testDirectory, \"ressources\");\n+\n+\t\texpectedPathes.add(alphaDirectory);\n+\t\texpectedPathes.add(srcDirectory);\n+\t\texpectedPathes.add(testDirectory);\n+\t\texpectedPathes.add(ressources);\n+\n+\t\tfinal List<String> patternList = new ArrayList<String>(2);\n+\t\tpatternList.add(\"alpha\");\n+\n+\t\tfinal Iterable<File> iterable = factory.createFileTreeIterable(project,\n+\t\t\t\tproject.getDirectory(), patternList);\n+\n+\t\tassertIsValidIterable(iterable);\n+\t\tassertIterableReturnsSet(expectedPathes, iterable);\n+\t}\n+\n+\tpublic void testSingleFile() throws Exception {\n+\t\tcreateFile(\"a.txt\");\n+\t\tcreateFile(\"a\", \"a.txt\");\n+\t\tcreateFile(\"a\", \"a\", \"a.txt\");\n+\t\tfinal File expectedFile = createFile(\"a\", \"b\", \"a.txt\");\n+\t\tcreateFile(\"a\", \"b\", \"a.c\");\n+\n+\t\tfinal String pattern = \"a\" + File.separator + \"b\" + File.separator\n+\t\t\t\t+ \"a.txt\";\n+\t\tfinal Iterable<File> iterable = factory.createFileTreeIterable(project,\n+\t\t\t\tproject.getDirectory(), Arrays.asList(pattern));\n+\t\tfinal Set<File> expectedPathes = Collections.singleton(expectedFile);\n+\t\tassertIsValidIterable(iterable);\n+\t\tassertIterableReturnsSet(expectedPathes, iterable);\n+\t}\n+\n+\t/**\n+\t * Tests if the specified {@link Iterable} returns the specified set of\n+\t * {@link File}s. The assertion will fail if the {@link Iterable} returns\n+\t * to much, to less files. It will also fail if the {@link Iterable} returns\n+\t * a file twice.\n+\t * \n+\t * @param expectedContent\n+\t *            the expected set of files.\n+\t * @param iterable\n+\t *            the {@link Iterable} to test.\n+\t */\n+\tprivate void assertIterableReturnsSet(Set<File> expectedContent,\n+\t\t\tIterable<File> iterable) {\n+\t\tfinal Set<File> returnedFiles = new HashSet<File>();\n+\t\tfinal List<File> doubleReturnedFiles = new ArrayList<File>();\n+\n+\t\tfinal Iterator<File> iterator = iterable.iterator();\n+\t\twhile (iterator.hasNext()) {\n+\t\t\tfinal File file = iterator.next();\n+\t\t\tif (!returnedFiles.add(file)) {\n+\t\t\t\tdoubleReturnedFiles.add(file);\n+\t\t\t}\n+\t\t}\n+\t\tfinal Set<File> missingFiles = new HashSet<File>();\n+\t\tfor (File file : expectedContent) {\n+\t\t\tif (!returnedFiles.contains(file)) {\n+\t\t\t\tmissingFiles.add(file);\n+\t\t\t}\n+\t\t}\n+\t\tif (!missingFiles.isEmpty()) {\n+\t\t\tfail(String.format(\"missing pathes: %s\", missingFiles));\n+\t\t}\n+\n+\t\tfinal Set<File> unexpectedFiles = new HashSet<File>();\n+\t\tfor (File file : returnedFiles) {\n+\t\t\tif (!expectedContent.contains(file)) {\n+\t\t\t\tunexpectedFiles.add(file);\n+\t\t\t}\n+\t\t}\n+\t\tif (!unexpectedFiles.isEmpty()) {\n+\t\t\tfail(String.format(\"unexpected pathes: %s\", unexpectedFiles));\n+\t\t}\n+\n+\t\tif (!doubleReturnedFiles.isEmpty()) {\n+\t\t\tfail(String.format(\"multiple times returned pathes: %s\",\n+\t\t\t\t\tdoubleReturnedFiles));\n+\t\t}\n+\n+\t}\n+\n+\tprivate static void assertIsValidIterable(Iterable<File> iterable) {\n+\t\tfinal Iterator<File> iterator = iterable.iterator();\n+\t\twhile (iterator.hasNext()) {\n+\t\t\titerator.next();\n+\t\t}\n+\t\ttry {\n+\t\t\titerator.next();\n+\t\t\tfail();\n+\t\t} catch (NoSuchElementException e) {\n+\t\t\t// expected\n+\t\t}\n+\t}\n+\n+\tprivate File createFile(String... path) throws IOException {\n+\t\tFile file = project.getDirectory();\n+\t\tfor (int i = 0; i < path.length; i++) {\n+\t\t\tfile = new File(file, path[i]);\n+\t\t\tif (i == path.length - 1) {\n+\t\t\t\tfile.getParentFile().mkdirs();\n+\t\t\t\tfile.createNewFile();\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\t\treturn file;\n+\t}\n+}\n-- \n1.5.2.5\n"},{"id":"76519","messageId":"1210424440-13886-23-git-send-email-florianskarten@web.de","threadId":"13461","inReplyTo":"1210424440-13886-1-git-send-email-florianskarten@web.de","subject":"[JGIT PATCH 22/22] Added a \"add\" command to the git like command line tool.","fromName":"Florian Koeberle","fromEmail":"florianskarten@web.de","sentAt":"2008-05-10T13:00:40Z","receivedAt":"2008-05-10T13:00:40Z","isPatch":true,"sender":{"key":"florianskarten@web.de","avatar":null},"body":"---\n .../src/org/spearce/jgit/pgm/AddCommand.java       |   96 ++++++++++++++++++++\n .../src/org/spearce/jgit/pgm/MainProgram.java      |    1 +\n 2 files changed, 97 insertions(+), 0 deletions(-)\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/pgm/AddCommand.java\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/pgm/AddCommand.java b/org.spearce.jgit/src/org/spearce/jgit/pgm/AddCommand.java\nnew file mode 100644\nindex 0000000..f8d86b1\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/pgm/AddCommand.java\n@@ -0,0 +1,96 @@\n+/*\n+ *  Copyright (C) 2008 Florian KÃ¶berle\n+ *\n+ *  This library is free software; you can redistribute it and/or\n+ *  modify it under the terms of the GNU General Public\n+ *  License, version 2, as published by the Free Software Foundation.\n+ *\n+ *  This library is distributed in the hope that it will be useful,\n+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+ *  General Public License for more details.\n+ *\n+ *  You should have received a copy of the GNU General Public\n+ *  License along with this library; if not, write to the Free Software\n+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301\n+ */\n+package org.spearce.jgit.pgm;\n+\n+import java.io.File;\n+import java.io.IOException;\n+import java.util.Arrays;\n+\n+import org.spearce.jgit.errors.InvalidPatternException;\n+import org.spearce.jgit.lib.GitIndex;\n+import org.spearce.jgit.lib.Project;\n+import org.spearce.jgit.lib.ProjectSeeker;\n+import org.spearce.jgit.lib.Repository;\n+import org.spearce.jgit.lib.GitIndex.Entry;\n+import org.spearce.jgit.lib.fileiteration.FileIterableFactoryForAddCommand;\n+\n+/**\n+ * This class is immutable. It's {@link #execute} method is used to add files to\n+ * the index.\n+ * \n+ * @author Florian KÃ¶berle\n+ * \n+ */\n+public class AddCommand implements Command {\n+\t/**\n+\t * Use this instance instead of creating a new ${link AddCommand}. You don't\n+\t * need to create an instance of this class as it is immutable and not\n+\t * configurable.\n+\t */\n+\tpublic static AddCommand INSTANCE = new AddCommand();\n+\n+\t/**\n+\t * Adds the specified files to the index.\n+\t * \n+\t * @param args\n+\t *            can contain \"*.Suffix\" patterns, files and directories.\n+\t */\n+\tpublic void execute(String... args) throws IOException {\n+\t\tfinal ProjectSeeker projectFactory = new ProjectSeeker();\n+\t\tfinal Project project = projectFactory.findProject();\n+\t\tfinal Repository repository = project.getRepository();\n+\t\ttry {\n+\t\t\tfinal GitIndex gitIndex = repository.getIndex();\n+\t\t\tfinal File projectDirectory = project.getDirectory();\n+\t\t\tfinal String workingDirectoryString = System\n+\t\t\t\t\t.getProperty(\"user.dir\");\n+\t\t\tif (workingDirectoryString == null) {\n+\t\t\t\tthrow new UnableToDetermineWorkingDirectory();\n+\t\t\t}\n+\t\t\tfinal File workingDirectory = new File(workingDirectoryString);\n+\t\t\tfinal FileIterableFactoryForAddCommand iterableFactory = new FileIterableFactoryForAddCommand();\n+\t\t\tfinal Iterable<File> fileIterable = iterableFactory\n+\t\t\t\t\t.createFileTreeIterable(project, workingDirectory, Arrays\n+\t\t\t\t\t\t\t.asList(args));\n+\t\t\tfor (File path : fileIterable) {\n+\t\t\t\tif (path.isFile()) {\n+\t\t\t\t\tEntry entry = gitIndex.add(projectDirectory, path);\n+\t\t\t\t\tentry.setAssumeValid(false);\n+\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\tgitIndex.write();\n+\t\t} catch (UnableToDetermineWorkingDirectory e) {\n+\t\t\tSystem.err.println(\"Unable to determine working directory\");\n+\t\t\tSystem.exit(1);\n+\t\t} catch (InvalidPatternException e) {\n+\t\t\tSystem.err.printf(\"The pattern '%s' is invalid: %s\",\n+\t\t\t\t\te.getMessage(), e.getPattern());\n+\t\t\tSystem.exit(1);\n+\t\t} finally {\n+\t\t\trepository.close();\n+\t\t}\n+\t}\n+\n+\tpublic String getShortDescription() {\n+\t\treturn \"Adds one or more files to the index.\";\n+\t}\n+\n+\tprivate static class UnableToDetermineWorkingDirectory extends Exception {\n+\t\tprivate static final long serialVersionUID = -4229647819515644868L;\n+\t}\n+}\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/pgm/MainProgram.java b/org.spearce.jgit/src/org/spearce/jgit/pgm/MainProgram.java\nindex 7601f31..78aaccd 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/pgm/MainProgram.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/pgm/MainProgram.java\n@@ -35,6 +35,7 @@ public class MainProgram {\n \n \tstatic {\n \t\tfinal Map<String, Command> commands = new HashMap<String, Command>();\n+\t\tcommands.put(\"add\", AddCommand.INSTANCE);\n \t\tcommands.put(\"init\", InitCommand.INSTANCE);\n \t\tcommands.put(\"help\", HelpCommand.INSTANCE);\n \t\tcommandNameToObjectMap = Collections.unmodifiableMap(commands);\n-- \n1.5.2.5\n"},{"id":"76537","messageId":"200805102245.08295.robin.rosenberg.lists@dewire.com","threadId":"13461","inReplyTo":"1210424440-13886-1-git-send-email-florianskarten@web.de","subject":"Re: [JGIT PATCH 0/m] Implementation of a file tree iteration using ignore rules.","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg.lists@dewire.com","sentAt":"2008-05-10T20:45:08Z","receivedAt":"2008-05-10T20:45:08Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"lördagen den 10 maj 2008 15.00.18 skrev Florian Koeberle:\n> Hi\n> \nWelcome to the project Florian!\n\n> here are the patches.\n> \n> The implementation does a lot of performance optimizations:\n\nAll good, but it would be nice to have some of these comments in the javadocs too. I can\nsign Shawns comments and add a few on my own, not trying to be too picky and requiring\nyou to think of everyhing I don't. We always play rough with newcomers :)\n\nSee the rest  of my replies.\n\n-- robin\n"},{"id":"76538","messageId":"200805102245.16575.robin.rosenberg.lists@dewire.com","threadId":"13461","inReplyTo":"1210424440-13886-4-git-send-email-florianskarten@web.de","subject":"Re: [JGIT PATCH 03/22] Added a class Project which represents a project directory and it's repository.","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg.lists@dewire.com","sentAt":"2008-05-10T20:45:16Z","receivedAt":"2008-05-10T20:45:16Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"lördagen den 10 maj 2008 15.00.21 skrev Florian Koeberle:\n> Signed-off-by: Florian Koeberle <florianskarten@web.de>\n> +public class GitPathConstants {\n> +\t/**\n> +\t * The name of the repository directory in the project directory.\n> +\t */\n> +\tpublic static final String REPOSITORY_DIRECTORY_NAME = \".git\";\n> +\n> +\t/**\n> +\t * Contains the name of the objects directory in the repository directory.\n> +\t */\n> +\tpublic static final String OBJECTS_DIRECTORY_NAME = \"objects\";\n> +\n> +\t/**\n> +\t * Contains the name of the refs directory in the repository directory.\n> +\t */\n> +\tpublic static final String REFS_DIRECTORY_NAME = \"refs\";\n> +\t\n> +\t/**\n> +\t * Contains the name of the HEAD file in the repository directory.\n> +\t */\n> +\tpublic static final String HEAD_FILE_NAME = \"HEAD\";\n> +\n> +}\n\nSome of these we have as constansts in the Constants class. We should use them\nand put the new ones there too. I think we have a few literals of our own that should\ngo there tool. Don't be afraid of proposing changes to other people's code. We don't\nterritories.\n\n> diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Project.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Project.java\n> new file mode 100644\n> index 0000000..6e72486\n> --- /dev/null\n> +++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Project.java\nThis term is also used by Eclipse and has a different meaning. Could we\nuse something else, maybe WorkTree?\n> +public class ProjectFactory {\n\nLet Repository be the factory.\n\n> +\t\t} catch (RuntimeException e) {\n> +\t\t\trepository.close();\n> +\t\t\tthrow e;\n> +\t\t} catch (IOException e) {\n> +\t\t\trepository.close();\n> +\t\t\tthrow e;\n> +\t\t}\nWhy not finally() handling all Exceptions?\n\n-- robin\n"},{"id":"76539","messageId":"200805102245.26162.robin.rosenberg.lists@dewire.com","threadId":"13461","inReplyTo":"1210424440-13886-6-git-send-email-florianskarten@web.de","subject":"Re: [JGIT PATCH 05/22] Added ProjectSeeker class.","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg.lists@dewire.com","sentAt":"2008-05-10T20:45:26Z","receivedAt":"2008-05-10T20:45:26Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"> +/**\n> + * Use this class to create instances of {@link Project}.\n> + * \n> + * @author Florian KÃ¶berle\n> + * \n> + */\n> +public class ProjectSeeker {\n\nLet Repository do this.\n\n-- robin\n"},{"id":"76540","messageId":"200805102246.56436.robin.rosenberg.lists@dewire.com","threadId":"13461","inReplyTo":"1210424440-13886-9-git-send-email-florianskarten@web.de","subject":"Re: [JGIT PATCH 08/22] Added the iterface Rules.","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg.lists@dewire.com","sentAt":"2008-05-10T20:46:56Z","receivedAt":"2008-05-10T20:46:56Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"Typo in commit message\n\n> + * @author Florian KÃ¶berle\nWe do not use this javadoc field.\n\n> \\ No newline at end of file\nMinor comment. Avoid this. Easy to forget so we do often. Weeding out trailing\nwhitespace is also nice as that tend to make diff smaller.  Attached a script\nthat be used to ammend a commit so any new or changed lines do not have\ntrailing whitespace. Not fixing this won't be a showstopper as  you do not\nhave a lot of these things anyway.\n\n-- robin\n\n"},{"id":"76542","messageId":"200805102253.13033.robin.rosenberg.lists@dewire.com","threadId":"13461","inReplyTo":"1210424440-13886-12-git-send-email-florianskarten@web.de","subject":"Re: [JGIT PATCH 11/22] Added the class StarPattern.","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg.lists@dewire.com","sentAt":"2008-05-10T20:53:12Z","receivedAt":"2008-05-10T20:53:12Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"\nAgree with Shawn that we really should have fnmatch,  but then calling\nit StarPattern at least signals it isn't the real wildcard. I'd like to see a few more lines of javadoc at the class level here (and the othere paterns) even though it is not a  public class. We must think about our reputation on Ohloh (http://www.ohloh.net/projects/6895) :)\n\n-- robin\n"},{"id":"76543","messageId":"200805102253.20379.robin.rosenberg.lists@dewire.com","threadId":"13461","inReplyTo":"1210424440-13886-14-git-send-email-florianskarten@web.de","subject":"Re: [JGIT PATCH 13/22] Added the class ComplexFilePattern.","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg.lists@dewire.com","sentAt":"2008-05-10T20:53:20Z","receivedAt":"2008-05-10T20:53:20Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"lördagen den 10 maj 2008 15.00.31 skrev Florian Koeberle:\n> +class ComplexFilePattern implements FilePattern {\n> +\t/**\n> +\t * Can contain String and\n> +\t */\n\nCould you elaborate on this?\n\n-- robin\n"},{"id":"76544","messageId":"200805102253.32760.robin.rosenberg.lists@dewire.com","threadId":"13461","inReplyTo":"1210424440-13886-15-git-send-email-florianskarten@web.de","subject":"Re: [JGIT PATCH 14/22] Added the class IgnoreRuleListFactory.","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg.lists@dewire.com","sentAt":"2008-05-10T20:53:32Z","receivedAt":"2008-05-10T20:53:32Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"> +class IgnoreRuleListFactory {\n\nI was just going to suggest this too goes to Repository too... may wait until we\nput the pattern to more use. We also need to combine this via som hook with\nthe Eclise Team settings for ignoreable stuff. So, for now, no change.\n\n-- robin\n"},{"id":"76545","messageId":"200805102253.40509.robin.rosenberg.lists@dewire.com","threadId":"13461","inReplyTo":"1210424440-13886-19-git-send-email-florianskarten@web.de","subject":"Re: [JGIT PATCH 18/22] Added InvalidPatternException and PathNotInProjectDirectoryException","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg.lists@dewire.com","sentAt":"2008-05-10T20:53:40Z","receivedAt":"2008-05-10T20:53:40Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"> +++ b/org.spearce.jgit/src/org/spearce/jgit/errors/InvalidPatternException.java\n> +public class InvalidPatternException extends Exception {\n> +\tprivate static final long serialVersionUID = -606889225458579931L;\nWe have ignored these so far. The nice thing about not declaring them is\nthat if we start depending on the we get to see incompatibilities earlier. \nDeclaring them makes diagnosing incompatibilties harder.\n\n-- robin\n"},{"id":"76546","messageId":"200805102253.50641.robin.rosenberg.lists@dewire.com","threadId":"13461","inReplyTo":"1210424440-13886-20-git-send-email-florianskarten@web.de","subject":"Re: [JGIT PATCH 19/22] Added the class AddRuleListFactory.","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg.lists@dewire.com","sentAt":"2008-05-10T20:53:50Z","receivedAt":"2008-05-10T20:53:50Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"lördagen den 10 maj 2008 15.00.37 skrev Florian Koeberle:\n> +class AddRuleListFactory {\n> +\t/*\n> +\t * The add command of git 1.5.2.5 behaves a little bit stange: \"git add\n> +\t * a/\\*z\" adds the file \"a/b/xyz\" but \"git add a/x\\*\" does not.\n> +\t * \n> +\t * The first is parsed as pattern \"*z\" for whole directory tree \"a\". The\n> +\t * second is parsed as an path.\n> +\t * \nWhat do *you* do?\n\n> +\t */\n> +\n> +\tprivate static List<String> getRelativePath(File projectDirectory, File file)\n> +\t\t\tthrows PathNotInProjectDirectoryException, IOException {\n> +\t\tFile currentFile = file.getCanonicalFile();\n> +\t\tfinal LinkedList<String> relativePath = new LinkedList<String>();\n> +\t\twhile (!currentFile.equals(projectDirectory)) {\n> +\t\t\trelativePath.addFirst(currentFile.getName());\n> +\t\t\tcurrentFile = currentFile.getParentFile();\n> +\t\t\tif (currentFile == null) {\n> +\t\t\t\tthrow new PathNotInProjectDirectoryException();\n> +\t\t\t}\n> +\t\t}\n> +\t\treturn relativePath;\n> +\t}\n\nWould be nice to have this logic in a utility class.\n\n-- robin\n"},{"id":"76547","messageId":"200805102253.59158.robin.rosenberg.lists@dewire.com","threadId":"13461","inReplyTo":"1210424440-13886-22-git-send-email-florianskarten@web.de","subject":"Re: [JGIT PATCH 21/22] Added test class FileIterableFactoryForAddCommandTest.","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg.lists@dewire.com","sentAt":"2008-05-10T20:53:59Z","receivedAt":"2008-05-10T20:53:59Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"> +public class FileIterableFactoryForAddCommandTest extends TestCase {\n\nWe have RepositoryTestcase that we use for unit tests that require a test repository.\nConsider using it. If not usable, why not? Maybe we can fix that. It includes logic\nto clean on \"next\" and handle some messy problems of cleaning up and avoiding\nproblems when re-running failed tests under Windows (read \"locked files and directories\");\n\n-- robin\n"},{"id":"76548","messageId":"200805102254.07978.robin.rosenberg.lists@dewire.com","threadId":"13461","inReplyTo":"1210424440-13886-23-git-send-email-florianskarten@web.de","subject":"Re: [JGIT PATCH 22/22] Added a \"add\" command to the git like command line tool.","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg.lists@dewire.com","sentAt":"2008-05-10T20:54:07Z","receivedAt":"2008-05-10T20:54:07Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"> +/**\n> + * This class is immutable. It's {@link #execute} method is used to add files to\n> + * the index.\n\nChange the order of the sentences so the first sentence is the summary.\n\n-- robin\n"},{"id":"76563","messageId":"20080511001612.GJ29038@spearce.org","threadId":"13461","inReplyTo":"200805102245.08295.robin.rosenberg.lists@dewire.com","subject":"Re: [JGIT PATCH 0/m] Implementation of a file tree iteration using ignore rules.","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-05-11T00:16:12Z","receivedAt":"2008-05-11T00:16:12Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Robin Rosenberg <robin.rosenberg.lists@dewire.com> wrote:\n> lördagen den 10 maj 2008 15.00.18 skrev Florian Koeberle:\n> > \n> Welcome to the project Florian!\n> \n> > here are the patches.\n> > \n> > The implementation does a lot of performance optimizations:\n> \n> [...], not trying to be too picky and requiring\n> you to think of everyhing I don't. We always play rough with newcomers :)\n\nNot just newcomers, we play rough with everyone!  :-)\n\nPersonally, I love this environment.  Because of how tough everyone\nis on each other's patches I've learned more in the past few years\nhere working on Git than I have learned in 4x that amount of time\nworking elsewhere.\n\n-- \nShawn.\n"}]}