Browse Source

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
tags/v2.2.0.201212191850-r
Robin Rosenberg 11 years ago
parent
commit
af54f16635

+ 128
- 0
org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheIteratorTest.java View File

import org.eclipse.jgit.junit.JGitTestUtil; import org.eclipse.jgit.junit.JGitTestUtil;
import org.eclipse.jgit.lib.FileMode; import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.RepositoryTestCase; import org.eclipse.jgit.lib.RepositoryTestCase;
import org.eclipse.jgit.treewalk.AbstractTreeIterator;
import org.eclipse.jgit.treewalk.TreeWalk; import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.filter.PathFilterGroup; import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
import org.eclipse.jgit.util.FS; import org.eclipse.jgit.util.FS;
assertEquals(paths.length, pathIdx); 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 @Test
public void testTwoLevelSubtree_FilterPath() throws Exception { public void testTwoLevelSubtree_FilterPath() throws Exception {
final DirCache dc = DirCache.newInCore(); final DirCache dc = DirCache.newInCore();

+ 17
- 1
org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheIterator.java View File

public void reset() { public void reset() {
if (!first()) { if (!first()) {
ptr = treeStart; ptr = treeStart;
nextSubtreePos = 0;
currentEntry = null;
currentSubtree = null;
if (!eof()) if (!eof())
parseEntry(); parseEntry();
} }
if (currentSubtree != null) if (currentSubtree != null)
nextSubtreePos--; nextSubtreePos--;
ptr--; ptr--;
parseEntry();
parseEntry(false);
if (currentSubtree != null) if (currentSubtree != null)
ptr -= currentSubtree.getEntrySpan() - 1; ptr -= currentSubtree.getEntrySpan() - 1;
} }
} }


private void parseEntry() { private void parseEntry() {
parseEntry(true);
}

private void parseEntry(boolean forward) {
currentEntry = cache.getEntry(ptr); currentEntry = cache.getEntry(ptr);
final byte[] cep = currentEntry.path; 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()) { if (nextSubtreePos != tree.getChildCount()) {
final DirCacheTree s = tree.getChild(nextSubtreePos); final DirCacheTree s = tree.getChild(nextSubtreePos);
if (s.contains(cep, pathOffset, cep.length)) { if (s.contains(cep, pathOffset, cep.length)) {

+ 5
- 0
org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheTree.java View File

return aPos; return aPos;
return -1; return -1;
} }

@Override
public String toString() {
return getNameString();
}
} }

Loading…
Cancel
Save