DirCacheIterator: Fix reset() and back()
reset() was broken and probably only worked when the position was at the beginning. More serious was that back() sometimes descended into the tree rather than skipping backward at the same level. Sometimes this would result in false conflicts, but one could suspect silent errors too. back() is called by the NamingConflictTreeWalk when looking for directory/file conflicts. Also added toString to DirCacheTree to simplify debugging. Bug: 396127 Change-Id: Iaa1b4e20e623d84c2e5ac26748f42e991080dbcd
This commit is contained in:
parent
138a2b06c8
commit
af54f16635
|
@ -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;
|
||||
|
@ -252,6 +253,133 @@ public void testTwoLevelSubtree_Recursive() throws Exception {
|
|||
assertEquals(paths.length, pathIdx);
|
||||
}
|
||||
|
||||
@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();
|
||||
|
|
|
@ -169,6 +169,9 @@ public int idOffset() {
|
|||
public void reset() {
|
||||
if (!first()) {
|
||||
ptr = treeStart;
|
||||
nextSubtreePos = 0;
|
||||
currentEntry = null;
|
||||
currentSubtree = null;
|
||||
if (!eof())
|
||||
parseEntry();
|
||||
}
|
||||
|
@ -203,16 +206,29 @@ public void back(int delta) {
|
|||
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)) {
|
||||
|
|
|
@ -552,4 +552,9 @@ private static int slash(final byte[] a, int aPos) {
|
|||
return aPos;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getNameString();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue