Merge "Fix hidden field warning" into stable-2.2
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheIteratorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheIteratorTest.java
index 7524413..6b3f700 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheIteratorTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheIteratorTest.java
@@ -55,6 +55,7 @@
 import org.eclipse.jgit.junit.JGitTestUtil;
 import org.eclipse.jgit.lib.FileMode;
 import org.eclipse.jgit.lib.RepositoryTestCase;
+import org.eclipse.jgit.treewalk.AbstractTreeIterator;
 import org.eclipse.jgit.treewalk.TreeWalk;
 import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
 import org.eclipse.jgit.util.FS;
@@ -253,6 +254,133 @@
 	}
 
 	@Test
+	public void testReset() throws Exception {
+		final DirCache dc = DirCache.newInCore();
+
+		final FileMode mode = FileMode.REGULAR_FILE;
+		final String[] paths = { "a.", "a/b", "a/c/e", "a/c/f", "a/d", "a0b" };
+		final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
+		for (int i = 0; i < paths.length; i++) {
+			ents[i] = new DirCacheEntry(paths[i]);
+			ents[i].setFileMode(mode);
+		}
+
+		final DirCacheBuilder b = dc.builder();
+		for (int i = 0; i < ents.length; i++)
+			b.add(ents[i]);
+		b.finish();
+
+		DirCacheIterator dci = new DirCacheIterator(dc);
+		assertFalse(dci.eof());
+		assertEquals("a.", dci.getEntryPathString());
+		dci.next(1);
+		assertFalse(dci.eof());
+		assertEquals("a", dci.getEntryPathString());
+		dci.next(1);
+		assertFalse(dci.eof());
+		assertEquals("a0b", dci.getEntryPathString());
+		dci.next(1);
+		assertTrue(dci.eof());
+
+		// same entries the second time
+		dci.reset();
+		assertFalse(dci.eof());
+		assertEquals("a.", dci.getEntryPathString());
+		dci.next(1);
+		assertFalse(dci.eof());
+		assertEquals("a", dci.getEntryPathString());
+		dci.next(1);
+		assertFalse(dci.eof());
+		assertEquals("a0b", dci.getEntryPathString());
+		dci.next(1);
+		assertTrue(dci.eof());
+
+		// Step backwards
+		dci.back(1);
+		assertFalse(dci.eof());
+		assertEquals("a0b", dci.getEntryPathString());
+		dci.back(1);
+		assertFalse(dci.eof());
+		assertEquals("a", dci.getEntryPathString());
+		dci.back(1);
+		assertFalse(dci.eof());
+		assertEquals("a.", dci.getEntryPathString());
+		assertTrue(dci.first());
+
+		// forward
+		assertFalse(dci.eof());
+		assertEquals("a.", dci.getEntryPathString());
+		dci.next(1);
+		assertFalse(dci.eof());
+		assertEquals("a", dci.getEntryPathString());
+		dci.next(1);
+		assertFalse(dci.eof());
+		assertEquals("a0b", dci.getEntryPathString());
+		dci.next(1);
+		assertTrue(dci.eof());
+
+		// backwqrd halways, and forward again
+		dci.back(1);
+		assertFalse(dci.eof());
+		assertEquals("a0b", dci.getEntryPathString());
+		dci.back(1);
+		assertFalse(dci.eof());
+		assertEquals("a", dci.getEntryPathString());
+
+		dci.next(1);
+		assertFalse(dci.eof());
+		assertEquals("a0b", dci.getEntryPathString());
+		dci.next(1);
+		assertTrue(dci.eof());
+
+		dci.reset(); // a.
+		dci.next(1); // a
+		AbstractTreeIterator sti = dci.createSubtreeIterator(null);
+		assertEquals("a/b", sti.getEntryPathString());
+		sti.next(1);
+		assertEquals("a/c", sti.getEntryPathString());
+		sti.next(1);
+		assertEquals("a/d", sti.getEntryPathString());
+		sti.back(2);
+		assertEquals("a/b", sti.getEntryPathString());
+
+	}
+
+	@Test
+	public void testBackBug396127() throws Exception {
+		final DirCache dc = DirCache.newInCore();
+
+		final FileMode mode = FileMode.REGULAR_FILE;
+		final String[] paths = { "git-gui/po/fr.po",
+				"git_remote_helpers/git/repo.py" };
+		final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
+		for (int i = 0; i < paths.length; i++) {
+			ents[i] = new DirCacheEntry(paths[i]);
+			ents[i].setFileMode(mode);
+		}
+
+		final DirCacheBuilder b = dc.builder();
+		for (int i = 0; i < ents.length; i++)
+			b.add(ents[i]);
+		b.finish();
+
+		DirCacheIterator dci = new DirCacheIterator(dc);
+		assertFalse(dci.eof());
+		assertEquals("git-gui", dci.getEntryPathString());
+		dci.next(1);
+		assertFalse(dci.eof());
+		assertEquals("git_remote_helpers", dci.getEntryPathString());
+		dci.back(1);
+		assertFalse(dci.eof());
+		assertEquals("git-gui", dci.getEntryPathString());
+		dci.next(1);
+		assertEquals("git_remote_helpers", dci.getEntryPathString());
+		dci.next(1);
+		assertTrue(dci.eof());
+
+	}
+
+	@Test
 	public void testTwoLevelSubtree_FilterPath() throws Exception {
 		final DirCache dc = DirCache.newInCore();
 
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheIterator.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheIterator.java
index e685e0c..706e057 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheIterator.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheIterator.java
@@ -169,6 +169,9 @@
 	public void reset() {
 		if (!first()) {
 			ptr = treeStart;
+			nextSubtreePos = 0;
+			currentEntry = null;
+			currentSubtree = null;
 			if (!eof())
 				parseEntry();
 		}
@@ -203,16 +206,29 @@
 			if (currentSubtree != null)
 				nextSubtreePos--;
 			ptr--;
-			parseEntry();
+			parseEntry(false);
 			if (currentSubtree != null)
 				ptr -= currentSubtree.getEntrySpan() - 1;
 		}
 	}
 
 	private void parseEntry() {
+		parseEntry(true);
+	}
+
+	private void parseEntry(boolean forward) {
 		currentEntry = cache.getEntry(ptr);
 		final byte[] cep = currentEntry.path;
 
+		if (!forward) {
+			if (nextSubtreePos > 0) {
+				final DirCacheTree p = tree.getChild(nextSubtreePos - 1);
+				if (p.contains(cep, pathOffset, cep.length)) {
+					nextSubtreePos--;
+					currentSubtree = p;
+				}
+			}
+		}
 		if (nextSubtreePos != tree.getChildCount()) {
 			final DirCacheTree s = tree.getChild(nextSubtreePos);
 			if (s.contains(cep, pathOffset, cep.length)) {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheTree.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheTree.java
index c71c913..5acde43 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheTree.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheTree.java
@@ -552,4 +552,9 @@
 				return aPos;
 		return -1;
 	}
+
+	@Override
+	public String toString() {
+		return getNameString();
+	}
 }