diff --git a/plugins/git4idea/src/git4idea/history/wholeTree/MediatorImpl.java b/plugins/git4idea/src/git4idea/history/wholeTree/MediatorImpl.java index 8fb856167fa6..e811b681b3d8 100644 --- a/plugins/git4idea/src/git4idea/history/wholeTree/MediatorImpl.java +++ b/plugins/git4idea/src/git4idea/history/wholeTree/MediatorImpl.java @@ -52,7 +52,9 @@ public class MediatorImpl implements Mediator { return StepType.STOP; } - myTableWrapper.appendResult(ticket, result, parents); + if (! result.isEmpty()) { + myTableWrapper.appendResult(ticket, result, parents); + } if (myTableWrapper.isSuspend()) { return StepType.PAUSE; } diff --git a/plugins/git4idea/src/git4idea/history/wholeTree/TreeNavigationImpl.java b/plugins/git4idea/src/git4idea/history/wholeTree/TreeNavigationImpl.java index 28cecc18baca..339c11e85a9c 100644 --- a/plugins/git4idea/src/git4idea/history/wholeTree/TreeNavigationImpl.java +++ b/plugins/git4idea/src/git4idea/history/wholeTree/TreeNavigationImpl.java @@ -26,7 +26,9 @@ public class TreeNavigationImpl implements TreeNavigation, WireEventsListener { private final TreeMap myWireEvents; // created for some of wire events; idx of _commit_ private final TreeMap myRingIndex; + // maximum number of commits, after which index entry should be written private final int myCommitIndexInterval; + // maximum number of wire events, after which index entry should be written private final int myNumWiresInGroup; public TreeNavigationImpl(final int commitIndexInterval, final int numWiresInGroup) { @@ -102,6 +104,10 @@ public class TreeNavigationImpl implements TreeNavigation, WireEventsListener { return myWireEvents.tailMap(rowInclusive).values().iterator(); } + private Iterator createWireEventsBackIterator(int rowExclusive) { + return myWireEvents.headMap(rowExclusive, false).descendingMap().values().iterator(); + } + @Override public Ring getUsedWires(int row, ReadonlyList commits) { final Map.Entry entry = myRingIndex.floorEntry(row); @@ -184,21 +190,20 @@ public class TreeNavigationImpl implements TreeNavigation, WireEventsListener { } public void recountWires(final int fromIdx, final ReadonlyList commits) { - final Ring.IntegerRing ring = new Ring.IntegerRing(); - final Map recalculateMap = new HashMap(); - int runningCommitNumber = 0; // next after previous event + /*final Iterator backIterator = createWireEventsBackIterator(fromIdx); + int runningCommitNumber = backIterator.hasNext() ? backIterator.next().getCommitIdx() : 0; // next after previous event + // t_odo: group two iterators to optimize! + */ + Ring usedWires = getUsedWires(fromIdx, commits); + final Ring.IntegerRing ring = new Ring.IntegerRing(usedWires.getUsed()); + + int runningCommitNumber = 0; final Iterator iterator = createWireEventsIterator(fromIdx); for (; iterator.hasNext(); ) { final WireEvent we = iterator.next(); - for (int i = runningCommitNumber; i <= we.getCommitIdx(); i++) { - final CommitI commit = commits.get(i); - final Integer newWire = recalculateMap.get(commit.getWireNumber()); - if (newWire != null) { - commit.setWireNumber(newWire); - } - } + recountFragmentZwichem(commits, recalculateMap, runningCommitNumber, we.getCommitIdx()); runningCommitNumber = we.getCommitIdx() + 1; final int[] wireEnds = we.getWireEnds(); @@ -223,14 +228,32 @@ public class TreeNavigationImpl implements TreeNavigation, WireEventsListener { final int[] commitsStarts = we.getCommitsStarts(); if (commitsStarts.length > 0 && (! we.isEnd())) { for (int commitStart : commitsStarts) { + // wire number Integer corrected = recalculateMap.get(commitStart); - corrected = (corrected == null) ? commitStart : corrected; + int wasWireNumber = commits.get(commitStart).getWireNumber(); + corrected = (corrected == null) ? wasWireNumber : corrected; if (! ring.isNumUsed(corrected)) { final Integer newNum = ring.getFree(); - recalculateMap.put(commitStart, newNum); + recalculateMap.put(wasWireNumber, newNum); } } } } + recountFragmentZwichem(commits, recalculateMap, runningCommitNumber, commits.getSize() - 1); + } + + private void recountFragmentZwichem(ReadonlyList commits, + Map recalculateMap, + int runningCommitNumber, + int inclusive) { + if (! recalculateMap.isEmpty()) { + for (int i = runningCommitNumber; i <= inclusive; i++) { + final CommitI commit = commits.get(i); + final Integer newWire = recalculateMap.get(commit.getWireNumber()); + if (newWire != null) { + commit.setWireNumber(newWire); + } + } + } } } diff --git a/plugins/git4idea/tests/git4idea/tests/SkeletonBuilderTest.java b/plugins/git4idea/tests/git4idea/tests/SkeletonBuilderTest.java index 0fab4416ca63..9f8ae9dfc5ef 100644 --- a/plugins/git4idea/tests/git4idea/tests/SkeletonBuilderTest.java +++ b/plugins/git4idea/tests/git4idea/tests/SkeletonBuilderTest.java @@ -81,6 +81,7 @@ public class SkeletonBuilderTest extends TestCase { TreeNavigationImpl navigation, SkeletonBuilder builder, ReadonlyList.ArrayListWrapper commits) { + int wasSize = commits.getSize(); for (CommitHashPlusParents commitHashPlusParents : list) { final WireNumberCommitDecoration commitI = new WireNumberCommitDecoration(new Commit(commitHashPlusParents.getHash(), commitHashPlusParents.getTime(), @@ -88,7 +89,7 @@ public class SkeletonBuilderTest extends TestCase { commits.getDelegate().add(commitI); builder.consume(commitI, getParents(commitHashPlusParents), commits); } - navigation.recountWires(0, commits); + navigation.recountWires(wasSize == 0 ? 0 : (wasSize - 1), commits); navigation.recalcIndex(commits); } @@ -136,6 +137,162 @@ public class SkeletonBuilderTest extends TestCase { Assert.assertEquals(4, we1.getCommitIdx()); } + public void testTwoSteps() throws Exception { + final List list = read("1 2 3\n2 4\n3 5\n4 6\n5 6\n6 7\n7 8 9"); + final List step2 = read("8 10\n9 11\n10 12\n11 13\n12 14\n13 14\n14 15"); + // 4, 4 + final TreeNavigationImpl navigation = new TreeNavigationImpl(2, 2); + final SkeletonBuilder builder = new SkeletonBuilder(navigation); + final ReadonlyList.ArrayListWrapper commits = new ReadonlyList.ArrayListWrapper(); + fillData(list, navigation, builder, commits); + + testFirstStepResults(navigation, commits); + // end of first step + fillData(step2, navigation, builder, commits); + + testFirstStepResults(navigation, commits); + for (int i = 7; i < 14; i++) { + final CommitI commitI = (CommitI)commits.get(i); + // just because of the test data order + Assert.assertEquals("" + (i + 1), commitI.getHash().getString()); + } + Assert.assertEquals(0, commits.get(7).getWireNumber()); + Assert.assertEquals(1, commits.get(8).getWireNumber()); + Assert.assertEquals(0, commits.get(9).getWireNumber()); + Assert.assertEquals(1, commits.get(10).getWireNumber()); + Assert.assertEquals(0, commits.get(11).getWireNumber()); + Assert.assertEquals(1, commits.get(12).getWireNumber()); + Assert.assertEquals(0, commits.get(13).getWireNumber()); + + final Iterator iterator = navigation.createWireEventsIterator(0); + testFirstIteratorPart(iterator); + WireEvent we = iterator.next(); + + Assert.assertEquals(6, we.getCommitIdx()); + final int[] commitsStarts = we.getCommitsStarts(); + Assert.assertEquals(2, commitsStarts.length); + Assert.assertEquals(7, commitsStarts[0]); + Assert.assertEquals(8, commitsStarts[1]); + Assert.assertNull(we.getWireEnds()); + + we = iterator.next(); + Assert.assertEquals(12, we.getWireEnds()[0]); + Assert.assertEquals(13, we.getCommitIdx()); + final int[] commitsEnds = we.getCommitsEnds(); + Assert.assertEquals(2, commitsEnds.length); + Assert.assertEquals(11, commitsEnds[0]); + Assert.assertEquals(12, commitsEnds[1]); + + assertWires(navigation.getUsedWires(7, commits).getUsed(),0,1); + assertWires(navigation.getUsedWires(8, commits).getUsed(), 0,1); + assertWires(navigation.getUsedWires(9, commits).getUsed(), 0,1); + assertWires(navigation.getUsedWires(10, commits).getUsed(), 0,1); + assertWires(navigation.getUsedWires(11, commits).getUsed(), 0,1); + assertWires(navigation.getUsedWires(12, commits).getUsed(), 0,1); + assertWires(navigation.getUsedWires(13, commits).getUsed(), 0,1); + } + + public void testTwoStepsMinusLastElement() throws Exception { + final List list = read("1 2 3\n2 4\n3 5\n4 6\n5 6\n6 7\n7 8 9"); + final List step2 = read("8 10\n9 11\n10 12\n11 13\n12 14\n13 14"); + // 4, 4 + final TreeNavigationImpl navigation = new TreeNavigationImpl(2, 2); + final SkeletonBuilder builder = new SkeletonBuilder(navigation); + final ReadonlyList.ArrayListWrapper commits = new ReadonlyList.ArrayListWrapper(); + fillData(list, navigation, builder, commits); + + testFirstStepResults(navigation, commits); + // end of first step + fillData(step2, navigation, builder, commits); + + testFirstStepResults(navigation, commits); + for (int i = 7; i < 13; i++) { + final CommitI commitI = (CommitI)commits.get(i); + // just because of the test data order + Assert.assertEquals("" + (i + 1), commitI.getHash().getString()); + } + Assert.assertEquals(0, commits.get(7).getWireNumber()); + Assert.assertEquals(1, commits.get(8).getWireNumber()); + Assert.assertEquals(0, commits.get(9).getWireNumber()); + Assert.assertEquals(1, commits.get(10).getWireNumber()); + Assert.assertEquals(0, commits.get(11).getWireNumber()); + Assert.assertEquals(1, commits.get(12).getWireNumber()); + + final Iterator iterator = navigation.createWireEventsIterator(0); + testFirstIteratorPart(iterator); + WireEvent we = iterator.next(); + + Assert.assertEquals(6, we.getCommitIdx()); + final int[] commitsStarts = we.getCommitsStarts(); + Assert.assertEquals(2, commitsStarts.length); + Assert.assertEquals(7, commitsStarts[0]); + Assert.assertEquals(8, commitsStarts[1]); + Assert.assertNull(we.getWireEnds()); + + assertWires(navigation.getUsedWires(7, commits).getUsed(),0,1); + assertWires(navigation.getUsedWires(8, commits).getUsed(), 0,1); + assertWires(navigation.getUsedWires(9, commits).getUsed(), 0,1); + assertWires(navigation.getUsedWires(10, commits).getUsed(), 0,1); + assertWires(navigation.getUsedWires(11, commits).getUsed(), 0,1); + assertWires(navigation.getUsedWires(12, commits).getUsed(), 0,1); + } + + private void testFirstStepResults(TreeNavigationImpl navigation, ReadonlyList.ArrayListWrapper commits) { + for (int i = 0; i < 7; i++) { + final CommitI commitI = (CommitI)commits.get(i); + // just because of the test data order + Assert.assertEquals("" + (i + 1), commitI.getHash().getString()); + } + Assert.assertEquals(0, commits.get(0).getWireNumber()); + Assert.assertEquals(0, commits.get(1).getWireNumber()); + Assert.assertEquals(1, commits.get(2).getWireNumber()); + Assert.assertEquals(0, commits.get(3).getWireNumber()); + Assert.assertEquals(1, commits.get(4).getWireNumber()); + Assert.assertEquals(0, commits.get(5).getWireNumber()); + Assert.assertEquals(0, commits.get(6).getWireNumber()); + + final Iterator iterator = navigation.createWireEventsIterator(0); + testFirstIteratorPart(iterator); + WireEvent we; + + assertWires(navigation.getUsedWires(0, commits).getUsed()); + assertWires(navigation.getUsedWires(1, commits).getUsed(), 0,1); + assertWires(navigation.getUsedWires(2, commits).getUsed(), 0,1); + assertWires(navigation.getUsedWires(3, commits).getUsed(), 0,1); + assertWires(navigation.getUsedWires(4, commits).getUsed(), 0,1); + assertWires(navigation.getUsedWires(5, commits).getUsed(), 0,1); + assertWires(navigation.getUsedWires(6, commits).getUsed(), 0); + + final Iterator iterator1 = navigation.createWireEventsIterator(4); + we = iterator1.next(); + Assert.assertEquals(4, we.getWireEnds()[0]); + Assert.assertEquals(5, we.getCommitIdx()); + final int[] commitsEnds1 = we.getCommitsEnds(); + Assert.assertEquals(2, commitsEnds1.length); + Assert.assertEquals(3, commitsEnds1[0]); + Assert.assertEquals(4, commitsEnds1[1]); + } + + private void testFirstIteratorPart(Iterator iterator) { + WireEvent we = iterator.next(); + Assert.assertEquals(true, we.isStart()); + Assert.assertEquals(0, we.getCommitIdx()); + final int[] commitsStarts = we.getCommitsStarts(); + Assert.assertEquals(2, commitsStarts.length); + Assert.assertEquals(1, commitsStarts[0]); + Assert.assertEquals(2, commitsStarts[1]); + Assert.assertNull(we.getWireEnds()); + Assert.assertEquals(0, we.getCommitIdx()); + + we = iterator.next(); + Assert.assertEquals(4, we.getWireEnds()[0]); + Assert.assertEquals(5, we.getCommitIdx()); + final int[] commitsEnds = we.getCommitsEnds(); + Assert.assertEquals(2, commitsEnds.length); + Assert.assertEquals(3, commitsEnds[0]); + Assert.assertEquals(4, commitsEnds[1]); + } + public void testBranchAndMerge() throws Exception { final List list = read("1 2\n2 3 4\n3 5\n4 6\n5 7\n6 8\n7 8\n8 9\n9"); // 4, 4