{"thread":{"id":"14912","subject":"[EGIT PATCH 03/11] Notify AbstractTreeIterator implementations of skipped tree entries","startedAt":"2008-08-10T08:46:15Z","lastAt":"2008-08-14T05:20:00Z","messageCount":15,"participants":["Shawn O. Pearce","Robin Rosenberg"],"isPatch":true,"patchVersion":1,"patchTotal":11},"messages":[{"id":"86649","messageId":"1218357986-19671-1-git-send-email-spearce@spearce.org","threadId":"14912","inReplyTo":null,"subject":"[EGIT PATCH 00/11] Misc. cleanups and improvements","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-08-10T08:46:15Z","receivedAt":"2008-08-10T08:46:15Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"This really is two parts; the first fixes a couple of bugs and\nthe latter section expands our treewalk API to handle the Eclipse\nworkbench natively as well as expose APIs needed to integrate the\nDIRC format (.git/index) into the treewalk structure.\n\nShawn O. Pearce (11):\n  Fix RawParseUtils.endOfParagraph to work on all corner cases\n  Add test case for the RevCommit parsing code\n  Notify AbstractTreeIterator implementations of skipped tree entries\n  Allow AbstractTreeIterator subclasses to supply their own path array\n  Allow WorkingTreeIterators to define their prefix path when created\n  Add getTree to TreeWalk for locating the current iterator instance\n  Allow WorkingTreeIterator to track last modified time for entries\n  Expose the current entry's length, last modified in\n    WorkingTreeIterator\n  Expose idBuffer,idOffset in AbstractTreeIterator to applications\n  Add a TreeWalk iterator implementation for IContainer\n  Teach NB how to encode/decode an unsigned 16 bit integer\n\n .../spearce/egit/core/ContainerTreeIterator.java   |  181 +++++++++++++++++++\n .../spearce/jgit/revwalk/RevCommitParseTest.java   |  190 ++++++++++++++++++++\n .../jgit/treewalk/AbstractTreeIterator.java        |   79 ++++++++-\n .../spearce/jgit/treewalk/CanonicalTreeParser.java |    4 +-\n .../spearce/jgit/treewalk/EmptyTreeIterator.java   |    4 +-\n .../spearce/jgit/treewalk/FileTreeIterator.java    |    9 +\n .../src/org/spearce/jgit/treewalk/TreeWalk.java    |   36 ++++-\n .../spearce/jgit/treewalk/WorkingTreeIterator.java |   56 ++++++-\n org.spearce.jgit/src/org/spearce/jgit/util/NB.java |   35 ++++\n .../src/org/spearce/jgit/util/RawParseUtils.java   |   11 +-\n 10 files changed, 591 insertions(+), 14 deletions(-)\n create mode 100644 org.spearce.egit.core/src/org/spearce/egit/core/ContainerTreeIterator.java\n create mode 100644 org.spearce.jgit.test/tst/org/spearce/jgit/revwalk/RevCommitParseTest.java\n"},{"id":"86646","messageId":"1218357986-19671-2-git-send-email-spearce@spearce.org","threadId":"14912","inReplyTo":"1218357986-19671-1-git-send-email-spearce@spearce.org","subject":"[EGIT PATCH 01/11] Fix RawParseUtils.endOfParagraph to work on all corner cases","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-08-10T08:46:16Z","receivedAt":"2008-08-10T08:46:16Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"We rely on this method to find the end of the \"oneline\" part of a\ncommit message, which is then used in displays like the History\nview in EGit or in some tooltips.  However a number of weird commit\nformats were throwing its parsing off, causing us to split the text\nin a way we didn't expect (or want) to split it.\n\nThis change resolves the splitting by making sure we don't throw an\nIndexOutOfBoundsException from RevCommit.getShortMessage due to the\nend of the paragraph coming out before the beginning of it.  This\nhappened sometimes when the commit message was empty.\n\nWe also now properly trim the trailing LFs which end the paragraph,\nas these were showing up sometimes as spaces at the end of a short\nmessage string (as we do LF->space conversion prior to returning).\n\nSigned-off-by: Shawn O. Pearce <spearce@spearce.org>\n---\n .../src/org/spearce/jgit/util/RawParseUtils.java   |   11 ++++++-----\n 1 files changed, 6 insertions(+), 5 deletions(-)\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/util/RawParseUtils.java b/org.spearce.jgit/src/org/spearce/jgit/util/RawParseUtils.java\nindex f268ffc..dbc2e83 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/util/RawParseUtils.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/util/RawParseUtils.java\n@@ -422,20 +422,21 @@ public final class RawParseUtils {\n \t * \n \t * @param b\n \t *            buffer to scan.\n-\t * @param ptr\n+\t * @param start\n \t *            position in buffer to start the scan at. Most callers will\n \t *            want to pass the first position of the commit message (as\n \t *            found by {@link #commitMessage(byte[], int)}.\n \t * @return position of the LF at the end of the paragraph;\n \t *         <code>b.length</code> if no paragraph end could be located.\n \t */\n-\tpublic static final int endOfParagraph(final byte[] b, int ptr) {\n+\tpublic static final int endOfParagraph(final byte[] b, final int start) {\n+\t\tint ptr = start;\n \t\tfinal int sz = b.length;\n \t\twhile (ptr < sz && b[ptr] != '\\n')\n \t\t\tptr = next(b, ptr, '\\n');\n-\t\tif (ptr < sz && b[ptr] == '\\n')\n-\t\t\treturn ptr - 1;\n-\t\treturn sz;\n+\t\twhile (0 < ptr && start < ptr && b[ptr - 1] == '\\n')\n+\t\t\tptr--;\n+\t\treturn ptr;\n \t}\n \n \tprivate RawParseUtils() {\n-- \n1.6.0.rc2.219.g1250ab\n"},{"id":"86648","messageId":"1218357986-19671-3-git-send-email-spearce@spearce.org","threadId":"14912","inReplyTo":"1218357986-19671-2-git-send-email-spearce@spearce.org","subject":"[EGIT PATCH 02/11] Add test case for the RevCommit parsing code","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-08-10T08:46:17Z","receivedAt":"2008-08-10T08:46:17Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Most of these are to address the errors identified in getShortMessage\nwhen handling the different corner cases of a commit body.\n\nSigned-off-by: Shawn O. Pearce <spearce@spearce.org>\n---\n .../spearce/jgit/revwalk/RevCommitParseTest.java   |  190 ++++++++++++++++++++\n 1 files changed, 190 insertions(+), 0 deletions(-)\n create mode 100644 org.spearce.jgit.test/tst/org/spearce/jgit/revwalk/RevCommitParseTest.java\n\ndiff --git a/org.spearce.jgit.test/tst/org/spearce/jgit/revwalk/RevCommitParseTest.java b/org.spearce.jgit.test/tst/org/spearce/jgit/revwalk/RevCommitParseTest.java\nnew file mode 100644\nindex 0000000..2645337\n--- /dev/null\n+++ b/org.spearce.jgit.test/tst/org/spearce/jgit/revwalk/RevCommitParseTest.java\n@@ -0,0 +1,190 @@\n+/*\n+ * Copyright (C) 2008, Google Inc.\n+ *\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or\n+ * without modification, are permitted provided that the following\n+ * conditions are met:\n+ *\n+ * - Redistributions of source code must retain the above copyright\n+ *   notice, this list of conditions and the following disclaimer.\n+ *\n+ * - Redistributions in binary form must reproduce the above\n+ *   copyright notice, this list of conditions and the following\n+ *   disclaimer in the documentation and/or other materials provided\n+ *   with the distribution.\n+ *\n+ * - Neither the name of the Git Development Community nor the\n+ *   names of its contributors may be used to endorse or promote\n+ *   products derived from this software without specific prior\n+ *   written permission.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n+ * CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+package org.spearce.jgit.revwalk;\n+\n+import org.spearce.jgit.lib.ObjectId;\n+import org.spearce.jgit.lib.PersonIdent;\n+import org.spearce.jgit.lib.RepositoryTestCase;\n+\n+public class RevCommitParseTest extends RepositoryTestCase {\n+\tpublic void testParse_NoParents() throws Exception {\n+\t\tfinal ObjectId treeId = id(\"9788669ad918b6fcce64af8882fc9a81cb6aba67\");\n+\t\tfinal String authorName = \"A U. Thor\";\n+\t\tfinal String authorEmail = \"a_u_thor@example.com\";\n+\t\tfinal int authorTime = 1218123387;\n+\n+\t\tfinal String committerName = \"C O. Miter\";\n+\t\tfinal String committerEmail = \"comiter@example.com\";\n+\t\tfinal int committerTime = 1218123390;\n+\t\tfinal StringBuilder body = new StringBuilder();\n+\n+\t\tbody.append(\"tree \");\n+\t\tbody.append(treeId);\n+\t\tbody.append(\"\\n\");\n+\n+\t\tbody.append(\"author \");\n+\t\tbody.append(authorName);\n+\t\tbody.append(\" <\");\n+\t\tbody.append(authorEmail);\n+\t\tbody.append(\"> \");\n+\t\tbody.append(authorTime);\n+\t\tbody.append(\" +0700\\n\");\n+\n+\t\tbody.append(\"committer \");\n+\t\tbody.append(committerName);\n+\t\tbody.append(\" <\");\n+\t\tbody.append(committerEmail);\n+\t\tbody.append(\"> \");\n+\t\tbody.append(committerTime);\n+\t\tbody.append(\" -0500\\n\");\n+\n+\t\tbody.append(\"\\n\");\n+\n+\t\tfinal RevWalk rw = new RevWalk(db);\n+\t\tfinal RevCommit c;\n+\n+\t\tc = new RevCommit(id(\"9473095c4cb2f12aefe1db8a355fe3fafba42f67\"));\n+\t\tassertNull(c.getTree());\n+\t\tassertNull(c.parents);\n+\n+\t\tc.parseCanonical(rw, body.toString().getBytes(\"UTF-8\"));\n+\t\tassertNotNull(c.getTree());\n+\t\tassertEquals(treeId, c.getTree().getId());\n+\t\tassertSame(rw.lookupTree(treeId), c.getTree());\n+\n+\t\tassertNotNull(c.parents);\n+\t\tassertEquals(0, c.parents.length);\n+\t\tassertEquals(\"\", c.getFullMessage());\n+\n+\t\tfinal PersonIdent cAuthor = c.getAuthorIdent();\n+\t\tassertNotNull(cAuthor);\n+\t\tassertEquals(authorName, cAuthor.getName());\n+\t\tassertEquals(authorEmail, cAuthor.getEmailAddress());\n+\n+\t\tfinal PersonIdent cCommitter = c.getCommitterIdent();\n+\t\tassertNotNull(cCommitter);\n+\t\tassertEquals(committerName, cCommitter.getName());\n+\t\tassertEquals(committerEmail, cCommitter.getEmailAddress());\n+\t}\n+\n+\tprivate RevCommit create(final String msg) throws Exception {\n+\t\tfinal StringBuilder b = new StringBuilder();\n+\t\tb.append(\"tree 9788669ad918b6fcce64af8882fc9a81cb6aba67\\n\");\n+\t\tb.append(\"author A U. Thor <a_u_thor@example.com> 1218123387 +0700\\n\");\n+\t\tb.append(\"committer C O. Miter <c@example.com> 1218123390 -0500\\n\");\n+\t\tb.append(\"\\n\");\n+\t\tb.append(msg);\n+\n+\t\tfinal RevCommit c;\n+\t\tc = new RevCommit(id(\"9473095c4cb2f12aefe1db8a355fe3fafba42f67\"));\n+\t\tc.parseCanonical(new RevWalk(db), b.toString().getBytes(\"UTF-8\"));\n+\t\treturn c;\n+\t}\n+\n+\tpublic void testParse_WeirdHeaderOnlyCommit() throws Exception {\n+\t\tfinal StringBuilder b = new StringBuilder();\n+\t\tb.append(\"tree 9788669ad918b6fcce64af8882fc9a81cb6aba67\\n\");\n+\t\tb.append(\"author A U. Thor <a_u_thor@example.com> 1218123387 +0700\\n\");\n+\t\tb.append(\"committer C O. Miter <c@example.com> 1218123390 -0500\\n\");\n+\n+\t\tfinal RevCommit c;\n+\t\tc = new RevCommit(id(\"9473095c4cb2f12aefe1db8a355fe3fafba42f67\"));\n+\t\tc.parseCanonical(new RevWalk(db), b.toString().getBytes(\"UTF-8\"));\n+\n+\t\tassertEquals(\"\", c.getFullMessage());\n+\t\tassertEquals(\"\", c.getShortMessage());\n+\t}\n+\n+\tpublic void testParse_NoMessage() throws Exception {\n+\t\tfinal String msg = \"\";\n+\t\tfinal RevCommit c = create(msg);\n+\t\tassertEquals(msg, c.getFullMessage());\n+\t\tassertEquals(msg, c.getShortMessage());\n+\t}\n+\n+\tpublic void testParse_OnlyLFMessage() throws Exception {\n+\t\tfinal RevCommit c = create(\"\\n\");\n+\t\tassertEquals(\"\\n\", c.getFullMessage());\n+\t\tassertEquals(\"\", c.getShortMessage());\n+\t}\n+\n+\tpublic void testParse_ShortLineOnlyNoLF() throws Exception {\n+\t\tfinal String shortMsg = \"This is a short message.\";\n+\t\tfinal RevCommit c = create(shortMsg);\n+\t\tassertEquals(shortMsg, c.getFullMessage());\n+\t\tassertEquals(shortMsg, c.getShortMessage());\n+\t}\n+\n+\tpublic void testParse_ShortLineOnlyEndLF() throws Exception {\n+\t\tfinal String shortMsg = \"This is a short message.\";\n+\t\tfinal String fullMsg = shortMsg + \"\\n\";\n+\t\tfinal RevCommit c = create(fullMsg);\n+\t\tassertEquals(fullMsg, c.getFullMessage());\n+\t\tassertEquals(shortMsg, c.getShortMessage());\n+\t}\n+\n+\tpublic void testParse_ShortLineOnlyEmbeddedLF() throws Exception {\n+\t\tfinal String fullMsg = \"This is a\\nshort message.\";\n+\t\tfinal String shortMsg = fullMsg.replace('\\n', ' ');\n+\t\tfinal RevCommit c = create(fullMsg);\n+\t\tassertEquals(fullMsg, c.getFullMessage());\n+\t\tassertEquals(shortMsg, c.getShortMessage());\n+\t}\n+\n+\tpublic void testParse_ShortLineOnlyEmbeddedAndEndingLF() throws Exception {\n+\t\tfinal String fullMsg = \"This is a\\nshort message.\\n\";\n+\t\tfinal String shortMsg = \"This is a short message.\";\n+\t\tfinal RevCommit c = create(fullMsg);\n+\t\tassertEquals(fullMsg, c.getFullMessage());\n+\t\tassertEquals(shortMsg, c.getShortMessage());\n+\t}\n+\n+\tpublic void testParse_GitStyleMessage() throws Exception {\n+\t\tfinal String shortMsg = \"This fixes a bug.\";\n+\t\tfinal String body = \"We do it with magic and pixie dust and stuff.\\n\"\n+\t\t\t\t+ \"\\n\" + \"Signed-off-by: A U. Thor <author@example.com>\\n\";\n+\t\tfinal String fullMsg = shortMsg + \"\\n\" + \"\\n\" + body;\n+\t\tfinal RevCommit c = create(fullMsg);\n+\t\tassertEquals(fullMsg, c.getFullMessage());\n+\t\tassertEquals(shortMsg, c.getShortMessage());\n+\t}\n+\n+\tprivate static ObjectId id(final String str) {\n+\t\treturn ObjectId.fromString(str);\n+\t}\n+}\n-- \n1.6.0.rc2.219.g1250ab\n"},{"id":"86644","messageId":"1218357986-19671-4-git-send-email-spearce@spearce.org","threadId":"14912","inReplyTo":"1218357986-19671-3-git-send-email-spearce@spearce.org","subject":"[EGIT PATCH 03/11] Notify AbstractTreeIterator implementations of skipped tree entries","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-08-10T08:46:18Z","receivedAt":"2008-08-10T08:46:18Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Some tree iterators may benefit from knowing when their driving TreeWalk\nhas chosen to skip past their current entry and not report it to client\napplications.  This can be useful for an index update scenario where the\nclient application has applied a TreeFilter to only see the entries that\nit wants to modify in this session.\n\nBy default the new skip() method just calls next(), as most types of the\ntree iterator do not have this distinction between skipped entry and a\nnon-skipped entry.\n\nSigned-off-by: Shawn O. Pearce <spearce@spearce.org>\n---\n .../jgit/treewalk/AbstractTreeIterator.java        |   16 ++++++++++++++++\n .../src/org/spearce/jgit/treewalk/TreeWalk.java    |   13 ++++++++++++-\n 2 files changed, 28 insertions(+), 1 deletions(-)\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/treewalk/AbstractTreeIterator.java b/org.spearce.jgit/src/org/spearce/jgit/treewalk/AbstractTreeIterator.java\nindex 448c547..0c0257c 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/treewalk/AbstractTreeIterator.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/treewalk/AbstractTreeIterator.java\n@@ -46,6 +46,7 @@ import org.spearce.jgit.lib.Constants;\n import org.spearce.jgit.lib.FileMode;\n import org.spearce.jgit.lib.ObjectId;\n import org.spearce.jgit.lib.Repository;\n+import org.spearce.jgit.treewalk.filter.TreeFilter;\n \n /**\n  * Walks a Git tree (directory) in Git sort order.\n@@ -316,4 +317,19 @@ public abstract class AbstractTreeIterator {\n \t *             the tree is invalid.\n \t */\n \tpublic abstract void next() throws CorruptObjectException;\n+\n+\t/**\n+\t * Advance to the next tree entry, populating this iterator with its data.\n+\t * <p>\n+\t * This method behaves like {@link #next()} but is called by\n+\t * {@link TreeWalk} only if a {@link TreeFilter} was used and ruled out the\n+\t * current entry from the results. In such cases this tree iterator may\n+\t * perform special behavior.\n+\t * \n+\t * @throws CorruptObjectException\n+\t *             the tree is invalid.\n+\t */\n+\tpublic void skip() throws CorruptObjectException {\n+\t\tnext();\n+\t}\n }\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/treewalk/TreeWalk.java b/org.spearce.jgit/src/org/spearce/jgit/treewalk/TreeWalk.java\nindex 42f8b25..7ea16b5 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/treewalk/TreeWalk.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/treewalk/TreeWalk.java\n@@ -395,7 +395,7 @@ public class TreeWalk {\n \n \t\t\t\tcurrentHead = t;\n \t\t\t\tif (!filter.include(this)) {\n-\t\t\t\t\tpopEntriesEqual();\n+\t\t\t\t\tskipEntriesEqual();\n \t\t\t\t\tcontinue;\n \t\t\t\t}\n \n@@ -635,6 +635,17 @@ public class TreeWalk {\n \t\t}\n \t}\n \n+\tprivate void skipEntriesEqual() throws CorruptObjectException {\n+\t\tfinal AbstractTreeIterator ch = currentHead;\n+\t\tfor (int i = 0; i < trees.length; i++) {\n+\t\t\tfinal AbstractTreeIterator t = trees[i];\n+\t\t\tif (t.matches == ch) {\n+\t\t\t\tt.skip();\n+\t\t\t\tt.matches = null;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n \tprivate void exitSubtree() throws CorruptObjectException {\n \t\tdepth--;\n \t\tfor (int i = 0; i < trees.length; i++)\n-- \n1.6.0.rc2.219.g1250ab\n"},{"id":"86651","messageId":"1218357986-19671-5-git-send-email-spearce@spearce.org","threadId":"14912","inReplyTo":"1218357986-19671-4-git-send-email-spearce@spearce.org","subject":"[EGIT PATCH 04/11] Allow AbstractTreeIterator subclasses to supply their own path array","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-08-10T08:46:19Z","receivedAt":"2008-08-10T08:46:19Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Some forms of AbstractTreeIterator may already have the path buffer\nthey want their child iterator to use in memory when the child is\nbeing created.  Therefore they do not want the existing constructor\nas it would modify the parent's path buffer, and force the subclass\nto copy the new child's path.\n\nBy allowing subclass implementations to define their own path buffer\nwe must rely on them to do the right thing in terms of setting up a\nvalid buffer for iteration, but the implementation can avoid copies\nand unwanted data changes to the parent array.\n\nSigned-off-by: Shawn O. Pearce <spearce@spearce.org>\n---\n .../jgit/treewalk/AbstractTreeIterator.java        |   23 ++++++++++++++++++++\n 1 files changed, 23 insertions(+), 0 deletions(-)\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/treewalk/AbstractTreeIterator.java b/org.spearce.jgit/src/org/spearce/jgit/treewalk/AbstractTreeIterator.java\nindex 0c0257c..64bb5be 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/treewalk/AbstractTreeIterator.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/treewalk/AbstractTreeIterator.java\n@@ -146,6 +146,29 @@ public abstract class AbstractTreeIterator {\n \t}\n \n \t/**\n+\t * Create an iterator for a subtree of an existing iterator.\n+\t * <p>\n+\t * The caller is responsible for setting up the path of the child iterator.\n+\t * \n+\t * @param p\n+\t *            parent tree iterator.\n+\t * @param childPath\n+\t *            path array to be used by the child iterator. This path must\n+\t *            contain the path from the top of the walk to the first child\n+\t *            and must end with a '/'.\n+\t * @param childPathOffset\n+\t *            position within <code>childPath</code> where the child can\n+\t *            insert its data. The value at\n+\t *            <code>childPath[childPathOffset-1]</code> must be '/'.\n+\t */\n+\tprotected AbstractTreeIterator(final AbstractTreeIterator p,\n+\t\t\tfinal byte[] childPath, final int childPathOffset) {\n+\t\tparent = p;\n+\t\tpath = childPath;\n+\t\tpathOffset = childPathOffset;\n+\t}\n+\n+\t/**\n \t * Grow the path buffer larger.\n \t * \n \t * @param len\n-- \n1.6.0.rc2.219.g1250ab\n"},{"id":"86650","messageId":"1218357986-19671-6-git-send-email-spearce@spearce.org","threadId":"14912","inReplyTo":"1218357986-19671-5-git-send-email-spearce@spearce.org","subject":"[EGIT PATCH 05/11] Allow WorkingTreeIterators to define their prefix path when created","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-08-10T08:46:20Z","receivedAt":"2008-08-10T08:46:20Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"When iterating a subset of the working directory over the full\nrepository tree (e.g. a CanonicalTreeParser run in parallel in\nthe same TreeWalk) we need the working directory to know what\nprefix it must apply to all of its own generated paths so they\nmatch up with the paths of the CanonicalTreeParser coming from\nthe object database.\n\nThe prefix is only set on the root level, as we only need to\ninject it into the first iterator.  After that the shared path\nbuffer will ensure the subtree iterators (if any are created)\nwill have the proper path in them too.\n\nSigned-off-by: Shawn O. Pearce <spearce@spearce.org>\n---\n .../jgit/treewalk/AbstractTreeIterator.java        |   36 ++++++++++++++++++++\n .../spearce/jgit/treewalk/WorkingTreeIterator.java |   20 +++++++++++\n 2 files changed, 56 insertions(+), 0 deletions(-)\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/treewalk/AbstractTreeIterator.java b/org.spearce.jgit/src/org/spearce/jgit/treewalk/AbstractTreeIterator.java\nindex 64bb5be..cf67836 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/treewalk/AbstractTreeIterator.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/treewalk/AbstractTreeIterator.java\n@@ -39,6 +39,8 @@\n package org.spearce.jgit.treewalk;\n \n import java.io.IOException;\n+import java.nio.ByteBuffer;\n+import java.nio.CharBuffer;\n \n import org.spearce.jgit.errors.CorruptObjectException;\n import org.spearce.jgit.errors.IncorrectObjectTypeException;\n@@ -128,6 +130,40 @@ public abstract class AbstractTreeIterator {\n \t}\n \n \t/**\n+\t * Create a new iterator with no parent and a prefix.\n+\t * <p>\n+\t * The prefix path supplied is inserted in front of all paths generated by\n+\t * this iterator. It is intended to be used when an iterator is being\n+\t * created for a subsection of an overall repository and needs to be\n+\t * combined with other iterators that are created to run over the entire\n+\t * repository namespace.\n+\t * \n+\t * @param prefix\n+\t *            position of this iterator in the repository tree. The value\n+\t *            may be null or the empty string to indicate the prefix is the\n+\t *            root of the repository. A trailing slash ('/') is\n+\t *            automatically appended if the prefix does not end in '/'.\n+\t */\n+\tprotected AbstractTreeIterator(final String prefix) {\n+\t\tparent = null;\n+\n+\t\tif (prefix != null && prefix.length() > 0) {\n+\t\t\tfinal ByteBuffer b;\n+\n+\t\t\tb = Constants.CHARSET.encode(CharBuffer.wrap(prefix));\n+\t\t\tpathLen = b.limit();\n+\t\t\tpath = new byte[Math.max(DEFAULT_PATH_SIZE, pathLen + 1)];\n+\t\t\tb.get(path, 0, pathLen);\n+\t\t\tif (path[pathLen - 1] != '/')\n+\t\t\t\tpath[pathLen++] = '/';\n+\t\t\tpathOffset = pathLen;\n+\t\t} else {\n+\t\t\tpath = new byte[DEFAULT_PATH_SIZE];\n+\t\t\tpathOffset = 0;\n+\t\t}\n+\t}\n+\n+\t/**\n \t * Create an iterator for a subtree of an existing iterator.\n \t * \n \t * @param p\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/treewalk/WorkingTreeIterator.java b/org.spearce.jgit/src/org/spearce/jgit/treewalk/WorkingTreeIterator.java\nindex 73c4b8b..afac77b 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/treewalk/WorkingTreeIterator.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/treewalk/WorkingTreeIterator.java\n@@ -100,6 +100,26 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator {\n \t}\n \n \t/**\n+\t * Create a new iterator with no parent and a prefix.\n+\t * <p>\n+\t * The prefix path supplied is inserted in front of all paths generated by\n+\t * this iterator. It is intended to be used when an iterator is being\n+\t * created for a subsection of an overall repository and needs to be\n+\t * combined with other iterators that are created to run over the entire\n+\t * repository namespace.\n+\t * \n+\t * @param prefix\n+\t *            position of this iterator in the repository tree. The value\n+\t *            may be null or the empty string to indicate the prefix is the\n+\t *            root of the repository. A trailing slash ('/') is\n+\t *            automatically appended if the prefix does not end in '/'.\n+\t */\n+\tprotected WorkingTreeIterator(final String prefix) {\n+\t\tsuper(prefix);\n+\t\tnameEncoder = Constants.CHARSET.newEncoder();\n+\t}\n+\n+\t/**\n \t * Create an iterator for a subtree of an existing iterator.\n \t * \n \t * @param p\n-- \n1.6.0.rc2.219.g1250ab\n"},{"id":"86645","messageId":"1218357986-19671-7-git-send-email-spearce@spearce.org","threadId":"14912","inReplyTo":"1218357986-19671-6-git-send-email-spearce@spearce.org","subject":"[EGIT PATCH 06/11] Add getTree to TreeWalk for locating the current iterator instance","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-08-10T08:46:21Z","receivedAt":"2008-08-10T08:46:21Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Since TreeWalk creates new child iterators as it dives into a subtree\n(and pops them when it comes out of the subtree) we must allow callers\nto locate their current iterator if they need additional APIs from it.\n\nSigned-off-by: Shawn O. Pearce <spearce@spearce.org>\n---\n .../src/org/spearce/jgit/treewalk/TreeWalk.java    |   23 ++++++++++++++++++++\n 1 files changed, 23 insertions(+), 0 deletions(-)\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/treewalk/TreeWalk.java b/org.spearce.jgit/src/org/spearce/jgit/treewalk/TreeWalk.java\nindex 7ea16b5..9f373e6 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/treewalk/TreeWalk.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/treewalk/TreeWalk.java\n@@ -413,6 +413,29 @@ public class TreeWalk {\n \t}\n \n \t/**\n+\t * Obtain the tree iterator for the current entry.\n+\t * <p>\n+\t * Entering into (or exiting out of) a subtree causes the current tree\n+\t * iterator instance to be changed for the nth tree. This allows the tree\n+\t * iterators to manage only one list of items, with the diving handled by\n+\t * recursive trees.\n+\t * \n+\t * @param <T>\n+\t *            type of the tree iterator expected by the caller.\n+\t * @param nth\n+\t *            tree to obtain the current iterator of.\n+\t * @param clazz\n+\t *            type of the tree iterator expected by the caller.\n+\t * @return r the current iterator of the requested type; null if the tree\n+\t *         has no entry to match the current path.\n+\t */\n+\tpublic <T extends AbstractTreeIterator> T getTree(final int nth,\n+\t\t\tfinal Class<T> clazz) {\n+\t\tfinal AbstractTreeIterator t = trees[nth];\n+\t\treturn t.matches == currentHead ? (T) t : null;\n+\t}\n+\n+\t/**\n \t * Obtain the raw {@link FileMode} bits for the current entry.\n \t * <p>\n \t * Every added tree supplies mode bits, even if the tree does not contain\n-- \n1.6.0.rc2.219.g1250ab\n"},{"id":"86647","messageId":"1218357986-19671-8-git-send-email-spearce@spearce.org","threadId":"14912","inReplyTo":"1218357986-19671-7-git-send-email-spearce@spearce.org","subject":"[EGIT PATCH 07/11] Allow WorkingTreeIterator to track last modified time for entries","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-08-10T08:46:22Z","receivedAt":"2008-08-10T08:46:22Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"We need this last modified time to compare against the index to decide\nif a file is dirty or not.  Its computed on demand only for the items\nwe actually care about, as we don't need the last modified time for a\ndirectory.\n\nSigned-off-by: Shawn O. Pearce <spearce@spearce.org>\n---\n .../spearce/jgit/treewalk/FileTreeIterator.java    |    9 +++++++++\n .../spearce/jgit/treewalk/WorkingTreeIterator.java |   13 +++++++++++++\n 2 files changed, 22 insertions(+), 0 deletions(-)\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/treewalk/FileTreeIterator.java b/org.spearce.jgit/src/org/spearce/jgit/treewalk/FileTreeIterator.java\nindex 331f153..25425dd 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/treewalk/FileTreeIterator.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/treewalk/FileTreeIterator.java\n@@ -106,6 +106,8 @@ public class FileTreeIterator extends WorkingTreeIterator {\n \n \t\tprivate long length = -1;\n \n+\t\tprivate long lastModified;\n+\n \t\tFileEntry(final File f) {\n \t\t\tfile = f;\n \n@@ -138,6 +140,13 @@ public class FileTreeIterator extends WorkingTreeIterator {\n \t\t}\n \n \t\t@Override\n+\t\tpublic long getLastModified() {\n+\t\t\tif (lastModified == 0)\n+\t\t\t\tlastModified = file.lastModified();\n+\t\t\treturn lastModified;\n+\t\t}\n+\n+\t\t@Override\n \t\tpublic InputStream openInputStream() throws IOException {\n \t\t\treturn new FileInputStream(file);\n \t\t}\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/treewalk/WorkingTreeIterator.java b/org.spearce.jgit/src/org/spearce/jgit/treewalk/WorkingTreeIterator.java\nindex afac77b..cb4a089 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/treewalk/WorkingTreeIterator.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/treewalk/WorkingTreeIterator.java\n@@ -433,6 +433,19 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator {\n \t\tpublic abstract long getLength();\n \n \t\t/**\n+\t\t * Get the last modified time of this entry.\n+\t\t * <p>\n+\t\t * <b>Note: Efficient implementation required.</b>\n+\t\t * <p>\n+\t\t * The implementation of this method must be efficient. If a subclass\n+\t\t * needs to compute the value they should cache the reference within an\n+\t\t * instance member instead.\n+\t\t * \n+\t\t * @return time since the epoch (in ms) of the last change.\n+\t\t */\n+\t\tpublic abstract long getLastModified();\n+\n+\t\t/**\n \t\t * Get the name of this entry within its directory.\n \t\t * <p>\n \t\t * Efficient implementations are not required. The caller will obtain\n-- \n1.6.0.rc2.219.g1250ab\n"},{"id":"86652","messageId":"1218357986-19671-9-git-send-email-spearce@spearce.org","threadId":"14912","inReplyTo":"1218357986-19671-8-git-send-email-spearce@spearce.org","subject":"[EGIT PATCH 08/11] Expose the current entry's length, last modified in WorkingTreeIterator","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-08-10T08:46:23Z","receivedAt":"2008-08-10T08:46:23Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"We need the last modified time available to us in application level\ncode so we can pull the current WorkingTreeIterator from TreeWalk\nand then grab the last modified time off it to compare against the\nindex file.\n\nSigned-off-by: Shawn O. Pearce <spearce@spearce.org>\n---\n .../spearce/jgit/treewalk/WorkingTreeIterator.java |   19 +++++++++++++++++++\n 1 files changed, 19 insertions(+), 0 deletions(-)\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/treewalk/WorkingTreeIterator.java b/org.spearce.jgit/src/org/spearce/jgit/treewalk/WorkingTreeIterator.java\nindex cb4a089..05d9282 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/treewalk/WorkingTreeIterator.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/treewalk/WorkingTreeIterator.java\n@@ -259,6 +259,25 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator {\n \t\tpathLen = pathOffset + nameLen;\n \t}\n \n+\t/**\n+\t * Get the byte length of this entry.\n+\t * \n+\t * @return size of this file, in bytes.\n+\t */\n+\tpublic long getEntryLength() {\n+\t\treturn current().getLength();\n+\t}\n+\n+\t/**\n+\t * Get the last modified time of this entry.\n+\t * \n+\t * @return last modified time of this file, in milliseconds since the epoch\n+\t *         (Jan 1, 1970 UTC).\n+\t */\n+\tpublic long getEntryLastModified() {\n+\t\treturn current().getLastModified();\n+\t}\n+\n \tprivate static final Comparator<Entry> ENTRY_CMP = new Comparator<Entry>() {\n \t\tpublic int compare(final Entry o1, final Entry o2) {\n \t\t\tfinal byte[] a = o1.encodedName;\n-- \n1.6.0.rc2.219.g1250ab\n"},{"id":"86653","messageId":"1218357986-19671-10-git-send-email-spearce@spearce.org","threadId":"14912","inReplyTo":"1218357986-19671-9-git-send-email-spearce@spearce.org","subject":"[EGIT PATCH 09/11] Expose idBuffer,idOffset in AbstractTreeIterator to applications","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-08-10T08:46:24Z","receivedAt":"2008-08-10T08:46:24Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Application code needs to be able to efficiently copy an id from\nan iterator's current position to some buffer, such as in the\nindex file or a tree object, or any other data structure.  Doing\na conversion to ObjectId and then back again to the raw byte form\nis less efficient than just copying the bytes between two arrays.\n\nSo these methods must be public for performance reasons, even if\nit makes the object API slightly more obtuse.  Besides we still\nhave getEntryObjectId should applications prefer that approach\nand they don't need the performance.\n\nSigned-off-by: Shawn O. Pearce <spearce@spearce.org>\n---\n .../jgit/treewalk/AbstractTreeIterator.java        |    4 ++--\n .../spearce/jgit/treewalk/CanonicalTreeParser.java |    4 ++--\n .../spearce/jgit/treewalk/EmptyTreeIterator.java   |    4 ++--\n .../spearce/jgit/treewalk/WorkingTreeIterator.java |    4 ++--\n 4 files changed, 8 insertions(+), 8 deletions(-)\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/treewalk/AbstractTreeIterator.java b/org.spearce.jgit/src/org/spearce/jgit/treewalk/AbstractTreeIterator.java\nindex cf67836..6d7159c 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/treewalk/AbstractTreeIterator.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/treewalk/AbstractTreeIterator.java\n@@ -321,7 +321,7 @@ public abstract class AbstractTreeIterator {\n \t * @return byte array the implementation stores object IDs within.\n \t * @see #getEntryObjectId()\n \t */\n-\tprotected abstract byte[] idBuffer();\n+\tpublic abstract byte[] idBuffer();\n \n \t/**\n \t * Get the position within {@link #idBuffer()} of this entry's ObjectId.\n@@ -329,7 +329,7 @@ public abstract class AbstractTreeIterator {\n \t * @return offset into the array returned by {@link #idBuffer()} where the\n \t *         ObjectId must be copied out of.\n \t */\n-\tprotected abstract int idOffset();\n+\tpublic abstract int idOffset();\n \n \t/**\n \t * Create a new iterator for the current entry's subtree.\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/treewalk/CanonicalTreeParser.java b/org.spearce.jgit/src/org/spearce/jgit/treewalk/CanonicalTreeParser.java\nindex 56bcab0..55942ed 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/treewalk/CanonicalTreeParser.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/treewalk/CanonicalTreeParser.java\n@@ -112,12 +112,12 @@ public class CanonicalTreeParser extends AbstractTreeIterator {\n \t}\n \n \t@Override\n-\tprotected byte[] idBuffer() {\n+\tpublic byte[] idBuffer() {\n \t\treturn raw;\n \t}\n \n \t@Override\n-\tprotected int idOffset() {\n+\tpublic int idOffset() {\n \t\treturn rawPtr - Constants.OBJECT_ID_LENGTH;\n \t}\n \ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/treewalk/EmptyTreeIterator.java b/org.spearce.jgit/src/org/spearce/jgit/treewalk/EmptyTreeIterator.java\nindex 73557bc..09d2bde 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/treewalk/EmptyTreeIterator.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/treewalk/EmptyTreeIterator.java\n@@ -69,12 +69,12 @@ public class EmptyTreeIterator extends AbstractTreeIterator {\n \t}\n \n \t@Override\n-\tprotected byte[] idBuffer() {\n+\tpublic byte[] idBuffer() {\n \t\treturn zeroid;\n \t}\n \n \t@Override\n-\tprotected int idOffset() {\n+\tpublic int idOffset() {\n \t\treturn 0;\n \t}\n \ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/treewalk/WorkingTreeIterator.java b/org.spearce.jgit/src/org/spearce/jgit/treewalk/WorkingTreeIterator.java\nindex 05d9282..4ac711b 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/treewalk/WorkingTreeIterator.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/treewalk/WorkingTreeIterator.java\n@@ -131,7 +131,7 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator {\n \t}\n \n \t@Override\n-\tprotected byte[] idBuffer() {\n+\tpublic byte[] idBuffer() {\n \t\tif (contentIdFromPtr == ptr - 1)\n \t\t\treturn contentId;\n \t\tif (entries == EOF)\n@@ -229,7 +229,7 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator {\n \t}\n \n \t@Override\n-\tprotected int idOffset() {\n+\tpublic int idOffset() {\n \t\treturn 0;\n \t}\n \n-- \n1.6.0.rc2.219.g1250ab\n"},{"id":"86655","messageId":"1218357986-19671-11-git-send-email-spearce@spearce.org","threadId":"14912","inReplyTo":"1218357986-19671-10-git-send-email-spearce@spearce.org","subject":"[EGIT PATCH 10/11] Add a TreeWalk iterator implementation for IContainer","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-08-10T08:46:25Z","receivedAt":"2008-08-10T08:46:25Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Treating the Eclipse workspace as a filesystem backend for TreeWalk\ncan give us some nice caching on the file modification times and on\ndirectory contents.  We also get nice APIs to open a file and read\nits contents.\n\nThis iterator allows combining a walk over an IContainer with any\nother sort of directory walk we may do, like against a stored tree\nobject in the object database or against the index file, or even\nany other IContainer in the workspace (e.g. diff two projects).\n\nSigned-off-by: Shawn O. Pearce <spearce@spearce.org>\n---\n .../spearce/egit/core/ContainerTreeIterator.java   |  181 ++++++++++++++++++++\n 1 files changed, 181 insertions(+), 0 deletions(-)\n create mode 100644 org.spearce.egit.core/src/org/spearce/egit/core/ContainerTreeIterator.java\n\ndiff --git a/org.spearce.egit.core/src/org/spearce/egit/core/ContainerTreeIterator.java b/org.spearce.egit.core/src/org/spearce/egit/core/ContainerTreeIterator.java\nnew file mode 100644\nindex 0000000..17b8414\n--- /dev/null\n+++ b/org.spearce.egit.core/src/org/spearce/egit/core/ContainerTreeIterator.java\n@@ -0,0 +1,181 @@\n+/*******************************************************************************\n+ * Copyright (C) 2008, Google Inc.\n+ *\n+ * All rights reserved. This program and the accompanying materials\n+ * are made available under the terms of the Eclipse Public License v1.0\n+ * See LICENSE for the full license text, also available.\n+ *******************************************************************************/\n+\n+package org.spearce.egit.core;\n+\n+import java.io.File;\n+import java.io.IOException;\n+import java.io.InputStream;\n+\n+import org.eclipse.core.resources.IContainer;\n+import org.eclipse.core.resources.IFile;\n+import org.eclipse.core.resources.IResource;\n+import org.eclipse.core.runtime.CoreException;\n+import org.spearce.egit.core.project.RepositoryMapping;\n+import org.spearce.jgit.errors.IncorrectObjectTypeException;\n+import org.spearce.jgit.lib.Constants;\n+import org.spearce.jgit.lib.FileMode;\n+import org.spearce.jgit.lib.ObjectId;\n+import org.spearce.jgit.lib.Repository;\n+import org.spearce.jgit.treewalk.AbstractTreeIterator;\n+import org.spearce.jgit.treewalk.WorkingTreeIterator;\n+import org.spearce.jgit.util.FS;\n+\n+/**\n+ * Adapts an Eclipse {@link IContainer} for use in a <code>TreeWalk</code>.\n+ * <p>\n+ * This iterator converts an Eclipse IContainer object into something that a\n+ * TreeWalk instance can iterate over in parallel with any other Git tree data\n+ * structure, such as another working directory tree from outside of the\n+ * workspace or a stored tree from a Repository object database.\n+ * <p>\n+ * Modification times provided by this iterator are obtained from the cache\n+ * Eclipse uses to track external resource modification. This can be faster, but\n+ * requires the user refresh their workspace when external modifications take\n+ * place. This is not really a concern as it is common practice to need to do a\n+ * workspace refresh after externally modifying a file.\n+ * \n+ * @see org.spearce.jgit.treewalk.TreeWalk\n+ */\n+public class ContainerTreeIterator extends WorkingTreeIterator {\n+\tprivate static String computePrefix(final IContainer base) {\n+\t\tfinal RepositoryMapping rm = RepositoryMapping.getMapping(base);\n+\t\tif (rm == null)\n+\t\t\tthrow new IllegalArgumentException(\"Not in a Git project: \" + base);\n+\t\treturn rm.getRepoRelativePath(base);\n+\t}\n+\n+\tprivate final IContainer node;\n+\n+\t/**\n+\t * Construct a new iterator from the workspace.\n+\t * <p>\n+\t * The iterator will support traversal over the named container, but only if\n+\t * it is contained within a project which has the Git repository provider\n+\t * connected and this resource is mapped into a Git repository. During the\n+\t * iteration the paths will be automatically generated to match the proper\n+\t * repository paths for this container's children.\n+\t * \n+\t * @param base\n+\t *            the part of the workspace the iterator will walk over.\n+\t */\n+\tpublic ContainerTreeIterator(final IContainer base) {\n+\t\tsuper(computePrefix(base));\n+\t\tnode = base;\n+\t}\n+\n+\tprivate ContainerTreeIterator(final WorkingTreeIterator p,\n+\t\t\tfinal IContainer base) {\n+\t\tsuper(p);\n+\t\tnode = base;\n+\t}\n+\n+\t@Override\n+\tpublic AbstractTreeIterator createSubtreeIterator(final Repository db)\n+\t\t\tthrows IncorrectObjectTypeException, IOException {\n+\t\tif (FileMode.TREE.equals(mode))\n+\t\t\treturn new ContainerTreeIterator(this,\n+\t\t\t\t\t(IContainer) ((ResourceEntry) current()).rsrc);\n+\t\telse\n+\t\t\tthrow new IncorrectObjectTypeException(ObjectId.zeroId(),\n+\t\t\t\t\tConstants.TYPE_TREE);\n+\t}\n+\n+\t@Override\n+\tprotected Entry[] getEntries() throws IOException {\n+\t\tfinal IResource[] all;\n+\t\ttry {\n+\t\t\tall = node.members(IContainer.INCLUDE_HIDDEN);\n+\t\t} catch (CoreException err) {\n+\t\t\tfinal IOException ioe = new IOException(err.getMessage());\n+\t\t\tioe.initCause(err);\n+\t\t\tthrow ioe;\n+\t\t}\n+\n+\t\tfinal Entry[] r = new Entry[all.length];\n+\t\tfor (int i = 0; i < r.length; i++)\n+\t\t\tr[i] = new ResourceEntry(all[i]);\n+\t\treturn r;\n+\t}\n+\n+\tstatic class ResourceEntry extends Entry {\n+\t\tfinal IResource rsrc;\n+\n+\t\tprivate final FileMode mode;\n+\n+\t\tprivate long length = -1;\n+\n+\t\tResourceEntry(final IResource f) {\n+\t\t\trsrc = f;\n+\n+\t\t\tswitch (f.getType()) {\n+\t\t\tcase IResource.FILE:\n+\t\t\t\tif (FS.INSTANCE.canExecute(asFile()))\n+\t\t\t\t\tmode = FileMode.EXECUTABLE_FILE;\n+\t\t\t\telse\n+\t\t\t\t\tmode = FileMode.REGULAR_FILE;\n+\t\t\t\tbreak;\n+\t\t\tcase IResource.FOLDER: {\n+\t\t\t\tfinal IContainer c = (IContainer) f;\n+\t\t\t\tif (c.findMember(\".git\") != null)\n+\t\t\t\t\tmode = FileMode.GITLINK;\n+\t\t\t\telse\n+\t\t\t\t\tmode = FileMode.TREE;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t\tdefault:\n+\t\t\t\tmode = FileMode.MISSING;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\n+\t\t@Override\n+\t\tpublic FileMode getMode() {\n+\t\t\treturn mode;\n+\t\t}\n+\n+\t\t@Override\n+\t\tpublic String getName() {\n+\t\t\treturn rsrc.getName();\n+\t\t}\n+\n+\t\t@Override\n+\t\tpublic long getLength() {\n+\t\t\tif (length < 0) {\n+\t\t\t\tif (rsrc instanceof IFile)\n+\t\t\t\t\tlength = asFile().length();\n+\t\t\t\telse\n+\t\t\t\t\tlength = 0;\n+\t\t\t}\n+\t\t\treturn length;\n+\t\t}\n+\n+\t\t@Override\n+\t\tpublic long getLastModified() {\n+\t\t\treturn rsrc.getLocalTimeStamp();\n+\t\t}\n+\n+\t\t@Override\n+\t\tpublic InputStream openInputStream() throws IOException {\n+\t\t\tif (rsrc instanceof IFile) {\n+\t\t\t\ttry {\n+\t\t\t\t\treturn ((IFile) rsrc).getContents(true);\n+\t\t\t\t} catch (CoreException err) {\n+\t\t\t\t\tfinal IOException ioe = new IOException(err.getMessage());\n+\t\t\t\t\tioe.initCause(err);\n+\t\t\t\t\tthrow ioe;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\tthrow new IOException(\"Not a regular file: \" + rsrc);\n+\t\t}\n+\n+\t\tprivate File asFile() {\n+\t\t\treturn ((IFile) rsrc).getLocation().toFile();\n+\t\t}\n+\t}\n+}\n-- \n1.6.0.rc2.219.g1250ab\n"},{"id":"86654","messageId":"1218357986-19671-12-git-send-email-spearce@spearce.org","threadId":"14912","inReplyTo":"1218357986-19671-11-git-send-email-spearce@spearce.org","subject":"[EGIT PATCH 11/11] Teach NB how to encode/decode an unsigned 16 bit integer","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-08-10T08:46:26Z","receivedAt":"2008-08-10T08:46:26Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"The DIRC (aka index) file format in Git uses a 16 bit unsigned int\nfield in at least one of the members for a file record.\n\nSigned-off-by: Shawn O. Pearce <spearce@spearce.org>\n---\n org.spearce.jgit/src/org/spearce/jgit/util/NB.java |   35 ++++++++++++++++++++\n 1 files changed, 35 insertions(+), 0 deletions(-)\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/util/NB.java b/org.spearce.jgit/src/org/spearce/jgit/util/NB.java\nindex 3af293a..ef21a4b 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/util/NB.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/util/NB.java\n@@ -91,6 +91,22 @@ public final class NB {\n \t}\n \n \t/**\n+\t * Convert sequence of 2 bytes (network byte order) into unsigned value.\n+\t * \n+\t * @param intbuf\n+\t *            buffer to acquire the 2 bytes of data from.\n+\t * @param offset\n+\t *            position within the buffer to begin reading from. This\n+\t *            position and the next byte after it (for a total of 2 bytes)\n+\t *            will be read.\n+\t * @return unsigned integer value that matches the 16 bits read.\n+\t */\n+\tpublic static int decodeUInt16(final byte[] intbuf, final int offset) {\n+\t\tint r = (intbuf[offset] << 8) & 0xff;\n+\t\treturn r | (intbuf[offset + 1] & 0xff);\n+\t}\n+\n+\t/**\n \t * Convert sequence of 4 bytes (network byte order) into signed value.\n \t * \n \t * @param intbuf\n@@ -148,6 +164,25 @@ public final class NB {\n \t}\n \n \t/**\n+\t * Write a 16 bit integer as a sequence of 2 bytes (network byte order).\n+\t * \n+\t * @param intbuf\n+\t *            buffer to write the 2 bytes of data into.\n+\t * @param offset\n+\t *            position within the buffer to begin writing to. This position\n+\t *            and the next byte after it (for a total of 2 bytes) will be\n+\t *            replaced.\n+\t * @param v\n+\t *            the value to write.\n+\t */\n+\tpublic static void encodeInt16(final byte[] intbuf, final int offset, int v) {\n+\t\tintbuf[offset + 1] = (byte) v;\n+\t\tv >>>= 8;\n+\n+\t\tintbuf[offset] = (byte) v;\n+\t}\n+\n+\t/**\n \t * Write a 32 bit integer as a sequence of 4 bytes (network byte order).\n \t * \n \t * @param intbuf\n-- \n1.6.0.rc2.219.g1250ab\n"},{"id":"87102","messageId":"200808132241.45402.robin.rosenberg.lists@dewire.com","threadId":"14912","inReplyTo":"1218357986-19671-11-git-send-email-spearce@spearce.org","subject":"Re: [EGIT PATCH 10/11] Add a TreeWalk iterator implementation for IContainer","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg.lists@dewire.com","sentAt":"2008-08-13T20:41:45Z","receivedAt":"2008-08-13T20:41:45Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"söndagen den 10 augusti 2008 10.46.25 skrev Shawn O. Pearce:\n> diff --git a/org.spearce.egit.core/src/org/spearce/egit/core/ContainerTreeIterator.java b/org.spearce.egit.core/src/org/spearce/egit/core/ContainerTreeIterator.java\n> new file mode 100644\n> index 0000000..17b8414\n> --- /dev/null\n> +++ b/org.spearce.egit.core/src/org/spearce/egit/core/ContainerTreeIterator.java\n...\n> +\t@Override\n> +\tprotected Entry[] getEntries() throws IOException {\n> +\t\tfinal IResource[] all;\n> +\t\ttry {\n> +\t\t\tall = node.members(IContainer.INCLUDE_HIDDEN);\n\nINCLUDE_HIDDEN is a 3.4 flag.\n\n-- robin\n"},{"id":"87143","messageId":"20080814041941.GA11232@spearce.org","threadId":"14912","inReplyTo":"200808132241.45402.robin.rosenberg.lists@dewire.com","subject":"Re: [EGIT PATCH 10/11] Add a TreeWalk iterator implementation for IContainer","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-08-14T04:19:41Z","receivedAt":"2008-08-14T04:19:41Z","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> söndagen den 10 augusti 2008 10.46.25 skrev Shawn O. Pearce:\n> > diff --git a/org.spearce.egit.core/src/org/spearce/egit/core/ContainerTreeIterator.java b/org.spearce.egit.core/src/org/spearce/egit/core/ContainerTreeIterator.java\n> > new file mode 100644\n> > index 0000000..17b8414\n> > --- /dev/null\n> > +++ b/org.spearce.egit.core/src/org/spearce/egit/core/ContainerTreeIterator.java\n> ...\n> > +\t@Override\n> > +\tprotected Entry[] getEntries() throws IOException {\n> > +\t\tfinal IResource[] all;\n> > +\t\ttry {\n> > +\t\t\tall = node.members(IContainer.INCLUDE_HIDDEN);\n> \n> INCLUDE_HIDDEN is a 3.4 flag.\n\nOh.  Can you amend that to be 0?\n\nI'd rather not rebuild my entire branch space just for this one minor\nchange so I can resend the patch.  I've got far too many large open\nbranches as it is, with everything depending on everything else.  :-|\n\n-- \nShawn.\n"},{"id":"87154","messageId":"200808140720.00837.robin.rosenberg.lists@dewire.com","threadId":"14912","inReplyTo":"20080814041941.GA11232@spearce.org","subject":"Re: [EGIT PATCH 10/11] Add a TreeWalk iterator implementation for IContainer","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg.lists@dewire.com","sentAt":"2008-08-14T05:20:00Z","receivedAt":"2008-08-14T05:20:00Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"torsdagen den 14 augusti 2008 06.19.41 skrev Shawn O. Pearce:\n> Robin Rosenberg <robin.rosenberg.lists@dewire.com> wrote:\n> > söndagen den 10 augusti 2008 10.46.25 skrev Shawn O. Pearce:\n> > INCLUDE_HIDDEN is a 3.4 flag.\n> \n> Oh.  Can you amend that to be 0?\nSure.\n> \n> I'd rather not rebuild my entire branch space just for this one minor\n> change so I can resend the patch.  I've got far too many large open\n> branches as it is, with everything depending on everything else.  :-|\n> \n\n-- robin\n"}]}