Mercurial > jhg
comparison src/org/tmatesoft/hg/internal/BlameHelper.java @ 674:cce0387c6041
Introduced dedicated IntSliceSeq/IntTuple in place of IntArray with subsequences
| author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
|---|---|
| date | Wed, 17 Jul 2013 15:40:51 +0200 |
| parents | 5f52074707b2 |
| children | 8625cba0a5a8 |
comparison
equal
deleted
inserted
replaced
| 673:545b1d4cc11d | 674:cce0387c6041 |
|---|---|
| 17 package org.tmatesoft.hg.internal; | 17 package org.tmatesoft.hg.internal; |
| 18 | 18 |
| 19 import static org.tmatesoft.hg.core.HgIterateDirection.OldToNew; | 19 import static org.tmatesoft.hg.core.HgIterateDirection.OldToNew; |
| 20 import static org.tmatesoft.hg.repo.HgRepository.NO_REVISION; | 20 import static org.tmatesoft.hg.repo.HgRepository.NO_REVISION; |
| 21 | 21 |
| 22 import java.util.Iterator; | |
| 22 import java.util.LinkedList; | 23 import java.util.LinkedList; |
| 23 import java.util.ListIterator; | 24 import java.util.ListIterator; |
| 24 | 25 |
| 25 import org.tmatesoft.hg.core.HgCallbackTargetException; | 26 import org.tmatesoft.hg.core.HgCallbackTargetException; |
| 26 import org.tmatesoft.hg.internal.DiffHelper.LineSequence; | 27 import org.tmatesoft.hg.internal.DiffHelper.LineSequence; |
| 217 private final HgBlameInspector insp; | 218 private final HgBlameInspector insp; |
| 218 private final int csetOrigin; | 219 private final int csetOrigin; |
| 219 private final int csetTarget; | 220 private final int csetTarget; |
| 220 private EqualBlocksCollector p2MergeCommon; | 221 private EqualBlocksCollector p2MergeCommon; |
| 221 private int csetMergeParent; | 222 private int csetMergeParent; |
| 222 private IntVector mergeRanges; | 223 private IntSliceSeq mergeRanges; |
| 223 private final AnnotateRev annotatedRevision; | 224 private final AnnotateRev annotatedRevision; |
| 224 private HgCallbackTargetException error; | 225 private HgCallbackTargetException error; |
| 225 | 226 |
| 226 public BlameBlockInspector(HgDataFile df, int fileRevIndex, HgBlameInspector inspector, int originCset, int targetCset) { | 227 public BlameBlockInspector(HgDataFile df, int fileRevIndex, HgBlameInspector inspector, int originCset, int targetCset) { |
| 227 assert inspector != null; | 228 assert inspector != null; |
| 233 } | 234 } |
| 234 | 235 |
| 235 public void setMergeParent2(EqualBlocksCollector p2Merge, int parentCset2) { | 236 public void setMergeParent2(EqualBlocksCollector p2Merge, int parentCset2) { |
| 236 p2MergeCommon = p2Merge; | 237 p2MergeCommon = p2Merge; |
| 237 csetMergeParent = parentCset2; | 238 csetMergeParent = parentCset2; |
| 238 mergeRanges = new IntVector(3*10, 3*10); | 239 mergeRanges = new IntSliceSeq(3, 10, 10); |
| 239 } | 240 } |
| 240 | 241 |
| 241 @Override | 242 @Override |
| 242 public void begin(LineSequence s1, LineSequence s2) { | 243 public void begin(LineSequence s1, LineSequence s2) { |
| 243 super.begin(s1, s2); | 244 super.begin(s1, s2); |
| 296 * NOW, lines from p2 are always reported as pure add (since we need their insertion point to be in p2, not in p1) | 297 * NOW, lines from p2 are always reported as pure add (since we need their insertion point to be in p2, not in p1) |
| 297 * and we try to consume p1 changes as soon as we see first p1's range | 298 * and we try to consume p1 changes as soon as we see first p1's range |
| 298 */ | 299 */ |
| 299 int s1TotalLines = s1To - s1From, s1ConsumedLines = 0, s1Start = s1From; | 300 int s1TotalLines = s1To - s1From, s1ConsumedLines = 0, s1Start = s1From; |
| 300 | 301 |
| 301 for (int i = 0; i < mergeRanges.size(); i += 3) { | 302 for (Iterator<IntTuple> it = mergeRanges.iterator(); it.hasNext();) { |
| 302 final int rangeOrigin = mergeRanges.get(i); | 303 IntTuple mergeRange = it.next(); |
| 303 final int rangeStart = mergeRanges.get(i+1); | 304 final int rangeOrigin = mergeRange.at(0); |
| 304 final int rangeLen = mergeRanges.get(i+2); | 305 final int rangeStart = mergeRange.at(1); |
| 305 final boolean lastRange = i+3 >= mergeRanges.size(); | 306 final int rangeLen = mergeRange.at(2); |
| 307 final boolean lastRange = it.hasNext(); | |
| 306 final int s1LinesLeft = s1TotalLines - s1ConsumedLines; | 308 final int s1LinesLeft = s1TotalLines - s1ConsumedLines; |
| 307 // how many lines we may report as changed (don't use more than in range unless it's the very last range) | 309 // how many lines we may report as changed (don't use more than in range unless it's the very last range) |
| 308 final int s1LinesToBorrow = lastRange ? s1LinesLeft : Math.min(s1LinesLeft, rangeLen); | 310 final int s1LinesToBorrow = lastRange ? s1LinesLeft : Math.min(s1LinesLeft, rangeLen); |
| 309 if (rangeOrigin != csetMergeParent && s1LinesToBorrow > 0) { | 311 if (rangeOrigin != csetMergeParent && s1LinesToBorrow > 0) { |
| 310 ChangeBlockImpl block = getChangeBlock(s1Start, s1LinesToBorrow, rangeStart, rangeLen); | 312 ChangeBlockImpl block = getChangeBlock(s1Start, s1LinesToBorrow, rangeStart, rangeLen); |
| 347 try { | 349 try { |
| 348 if (p2MergeCommon != null) { | 350 if (p2MergeCommon != null) { |
| 349 mergeRanges.clear(); | 351 mergeRanges.clear(); |
| 350 p2MergeCommon.combineAndMarkRangesWithTarget(s2From, s2To - s2From, csetOrigin, csetMergeParent, mergeRanges); | 352 p2MergeCommon.combineAndMarkRangesWithTarget(s2From, s2To - s2From, csetOrigin, csetMergeParent, mergeRanges); |
| 351 int insPoint = s1InsertPoint; // track changes to insertion point | 353 int insPoint = s1InsertPoint; // track changes to insertion point |
| 352 for (int i = 0; i < mergeRanges.size(); i += 3) { | 354 for (IntTuple mergeRange : mergeRanges) { |
| 353 int rangeOrigin = mergeRanges.get(i); | 355 int rangeOrigin = mergeRange.at(0); |
| 354 int rangeStart = mergeRanges.get(i+1); | 356 int rangeStart = mergeRange.at(1); |
| 355 int rangeLen = mergeRanges.get(i+2); | 357 int rangeLen = mergeRange.at(2); |
| 356 ChangeBlockImpl block = getAddBlock(rangeStart, rangeLen, insPoint); | 358 ChangeBlockImpl block = getAddBlock(rangeStart, rangeLen, insPoint); |
| 357 block.setOriginAndTarget(rangeOrigin, csetTarget); | 359 block.setOriginAndTarget(rangeOrigin, csetTarget); |
| 358 insp.added(block); | 360 insp.added(block); |
| 359 // indicate insPoint moved down number of lines we just reported | 361 // indicate insPoint moved down number of lines we just reported |
| 360 insPoint += rangeLen; | 362 insPoint += rangeLen; |
| 617 } | 619 } |
| 618 } | 620 } |
| 619 | 621 |
| 620 | 622 |
| 621 private static class EqualBlocksCollector implements DiffHelper.MatchInspector<LineSequence> { | 623 private static class EqualBlocksCollector implements DiffHelper.MatchInspector<LineSequence> { |
| 622 private final RangeSeq matches = new RangeSeq(); | 624 private final RangePairSeq matches = new RangePairSeq(); |
| 623 | 625 |
| 624 public void begin(LineSequence s1, LineSequence s2) { | 626 public void begin(LineSequence s1, LineSequence s2) { |
| 625 } | 627 } |
| 626 | 628 |
| 627 public void match(int startSeq1, int startSeq2, int matchLength) { | 629 public void match(int startSeq1, int startSeq2, int matchLength) { |
| 656 * intersects [start..start+length) with ranges of target lines, and based on the intersection | 658 * intersects [start..start+length) with ranges of target lines, and based on the intersection |
| 657 * breaks initial range into smaller ranges and records them into result, with marker to indicate | 659 * breaks initial range into smaller ranges and records them into result, with marker to indicate |
| 658 * whether the range is from initial range (markerSource) or is a result of the intersection with target | 660 * whether the range is from initial range (markerSource) or is a result of the intersection with target |
| 659 * (markerTarget) | 661 * (markerTarget) |
| 660 */ | 662 */ |
| 661 public void combineAndMarkRangesWithTarget(int start, int length, int markerSource, int markerTarget, IntVector result) { | 663 public void combineAndMarkRangesWithTarget(int start, int length, int markerSource, int markerTarget, IntSliceSeq result) { |
| 664 assert result.sliceSize() == 3; | |
| 662 int sourceStart = start, targetStart = start, sourceEnd = start + length; | 665 int sourceStart = start, targetStart = start, sourceEnd = start + length; |
| 663 for (int l = sourceStart; l < sourceEnd; l++) { | 666 for (int l = sourceStart; l < sourceEnd; l++) { |
| 664 if (matches.includesTargetLine(l)) { | 667 if (matches.includesTargetLine(l)) { |
| 665 // l is from target | 668 // l is from target |
| 666 if (sourceStart < l) { | 669 if (sourceStart < l) { |
| 667 // few lines from source range were not in the target, report them | 670 // few lines from source range were not in the target, report them |
| 668 result.add(markerSource); | 671 result.add(markerSource, sourceStart, l - sourceStart); |
| 669 result.add(sourceStart); | |
| 670 result.add(l - sourceStart); | |
| 671 } | 672 } |
| 672 // indicate the earliest line from source range to use | 673 // indicate the earliest line from source range to use |
| 673 sourceStart = l + 1; | 674 sourceStart = l + 1; |
| 674 } else { | 675 } else { |
| 675 // l is not in target | 676 // l is not in target |
| 676 if (targetStart < l) { | 677 if (targetStart < l) { |
| 677 // report lines from target range | 678 // report lines from target range |
| 678 result.add(markerTarget); | 679 result.add(markerTarget, targetStart, l - targetStart); |
| 679 result.add(targetStart); | |
| 680 result.add(l - targetStart); | |
| 681 } | 680 } |
| 682 // next line *may* be from target | 681 // next line *may* be from target |
| 683 targetStart = l + 1; | 682 targetStart = l + 1; |
| 684 } | 683 } |
| 685 } | 684 } |
| 686 // if source range end with line from target, sourceStart would be == sourceEnd, and we need to add range with markerTarget | 685 // if source range end with line from target, sourceStart would be == sourceEnd, and we need to add range with markerTarget |
| 687 // if source range doesn't end with target line, targetStart == sourceEnd, while sourceStart < sourceEnd | 686 // if source range doesn't end with target line, targetStart == sourceEnd, while sourceStart < sourceEnd |
| 688 if (sourceStart < sourceEnd) { | 687 if (sourceStart < sourceEnd) { |
| 689 assert targetStart == sourceEnd; | 688 assert targetStart == sourceEnd; |
| 690 // something left from the source range | 689 // something left from the source range |
| 691 result.add(markerSource); | 690 result.add(markerSource, sourceStart, sourceEnd - sourceStart); |
| 692 result.add(sourceStart); | |
| 693 result.add(sourceEnd - sourceStart); | |
| 694 } else if (targetStart < sourceEnd) { | 691 } else if (targetStart < sourceEnd) { |
| 695 assert sourceStart == sourceEnd; | 692 assert sourceStart == sourceEnd; |
| 696 result.add(markerTarget); | 693 result.add(markerTarget, targetStart, sourceEnd - targetStart); |
| 697 result.add(targetStart); | |
| 698 result.add(sourceEnd - targetStart); | |
| 699 } | 694 } |
| 700 } | 695 } |
| 701 } | 696 } |
| 702 | 697 |
| 703 private static class AnnotateRev implements RevisionDescriptor { | 698 private static class AnnotateRev implements RevisionDescriptor { |
| 768 bc.intersectWithTarget(7, 10, r); | 763 bc.intersectWithTarget(7, 10, r); |
| 769 for (int i = 0; i < r.size(); i+=2) { | 764 for (int i = 0; i < r.size(); i+=2) { |
| 770 System.out.printf("[%d..%d) ", r.get(i), r.get(i) + r.get(i+1)); | 765 System.out.printf("[%d..%d) ", r.get(i), r.get(i) + r.get(i+1)); |
| 771 } | 766 } |
| 772 System.out.println(); | 767 System.out.println(); |
| 773 r.clear(); | 768 IntSliceSeq mr = new IntSliceSeq(3); |
| 774 bc.combineAndMarkRangesWithTarget(0, 16, 508, 514, r); | 769 bc.combineAndMarkRangesWithTarget(0, 16, 508, 514, mr); |
| 775 for (int i = 0; i < r.size(); i+=3) { | 770 for (IntTuple t : mr) { |
| 776 System.out.printf("%d:[%d..%d) ", r.get(i), r.get(i+1), r.get(i+1) + r.get(i+2)); | 771 System.out.printf("%d:[%d..%d) ", t.at(0), t.at(1), t.at(1) + t.at(2)); |
| 777 } | 772 } |
| 778 } | 773 } |
| 779 } | 774 } |
