comparison src/org/tmatesoft/hg/internal/diff/BlameHelper.java @ 709:497e697636fc

Report merged lines as changed block if possible, not as a sequence of added/deleted blocks. To facilitate access to merge parent lines AddBlock got mergeLineAt() method that reports index of the line in the second parent (if any), while insertedAt() has been changed to report index in the first parent always
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Wed, 21 Aug 2013 16:23:27 +0200
parents 7839ff0bfd78
children
comparison
equal deleted inserted replaced
708:4ffc17c0b534 709:497e697636fc
377 final int rangeLen = mergeRange.at(2); 377 final int rangeLen = mergeRange.at(2);
378 final boolean lastRange = it.hasNext(); 378 final boolean lastRange = it.hasNext();
379 final int s1LinesLeft = s1TotalLines - s1ConsumedLines; 379 final int s1LinesLeft = s1TotalLines - s1ConsumedLines;
380 // how many lines we may report as changed (don't use more than in range unless it's the very last range) 380 // how many lines we may report as changed (don't use more than in range unless it's the very last range)
381 final int s1LinesToBorrow = lastRange ? s1LinesLeft : Math.min(s1LinesLeft, rangeLen); 381 final int s1LinesToBorrow = lastRange ? s1LinesLeft : Math.min(s1LinesLeft, rangeLen);
382 if (rangeOrigin != csetMergeParent && s1LinesToBorrow > 0) { 382 if (s1LinesToBorrow > 0) {
383 ChangeBlockImpl block = getChangeBlock(s1Start, s1LinesToBorrow, rangeStart, rangeLen); 383 ChangeBlockImpl block = getChangeBlock(s1Start, s1LinesToBorrow, rangeStart, rangeLen);
384 block.setOriginAndTarget(rangeOrigin, csetTarget); 384 block.setOriginAndTarget(rangeOrigin, csetTarget);
385 if (rangeOrigin == csetMergeParent) {
386 block.setMergeFromLine(p2MergeCommon.getLineInP2(rangeStart));
387 }
385 insp.changed(block); 388 insp.changed(block);
386 s1ConsumedLines += s1LinesToBorrow; 389 s1ConsumedLines += s1LinesToBorrow;
387 s1Start += s1LinesToBorrow; 390 s1Start += s1LinesToBorrow;
388 } else { 391 } else {
389 int blockInsPoint = rangeOrigin != csetMergeParent ? s1Start : p2MergeCommon.getLineInP2(rangeStart); 392 ChangeBlockImpl block = getAddBlock(rangeStart, rangeLen, s1Start);
390 ChangeBlockImpl block = getAddBlock(rangeStart, rangeLen, blockInsPoint);
391 block.setOriginAndTarget(rangeOrigin, csetTarget); 393 block.setOriginAndTarget(rangeOrigin, csetTarget);
394 if (rangeOrigin == csetMergeParent) {
395 block.setMergeFromLine(p2MergeCommon.getLineInP2(rangeStart));
396 }
392 insp.added(block); 397 insp.added(block);
393 } 398 }
394 } 399 }
395 if (s1ConsumedLines != s1TotalLines) { 400 if (s1ConsumedLines != s1TotalLines) {
396 assert s1ConsumedLines < s1TotalLines : String.format("Expected to process %d lines, but actually was %d", s1TotalLines, s1ConsumedLines); 401 assert s1ConsumedLines < s1TotalLines : String.format("Expected to process %d lines, but actually was %d", s1TotalLines, s1ConsumedLines);
397 // either there were no ranges from p1, whole s2From..s2To range came from p2, shall report as deleted 402 // either there were no ranges from p1, whole s2From..s2To range came from p2, shall report as deleted
398 // or the ranges found were not enough to consume whole s2From..s2To 403 // or the ranges found were not enough to consume whole s2From..s2To
399 // The "deletion point" is shifted to the end of last csetOrigin->csetTarget change 404 // The "deletion point" is shifted to the end of last csetOrigin->csetTarget change
400 int s2DeletePoint = s2From + s1ConsumedLines; 405 int s2DeletePoint = s2From + s1ConsumedLines;
401 ChangeBlockImpl block = new ChangeBlockImpl(annotatedRevision.origin, null, s1Start, s1To - s1Start, -1, -1, -1, s2DeletePoint); 406 ChangeBlockImpl block = getDeleteBlock(s1Start, s1To - s1Start, s2DeletePoint);
402 block.setOriginAndTarget(csetOrigin, csetTarget); 407 block.setOriginAndTarget(csetOrigin, csetTarget);
403 insp.deleted(block); 408 insp.deleted(block);
404 } 409 }
405 } else { 410 } else {
406 ChangeBlockImpl block = getChangeBlock(s1From, s1To - s1From, s2From, s2To - s2From); 411 ChangeBlockImpl block = getChangeBlock(s1From, s1To - s1From, s2From, s2To - s2From);
423 int insPoint = s1InsertPoint; // track changes to insertion point 428 int insPoint = s1InsertPoint; // track changes to insertion point
424 for (IntTuple mergeRange : mergeRanges) { 429 for (IntTuple mergeRange : mergeRanges) {
425 int rangeOrigin = mergeRange.at(0); 430 int rangeOrigin = mergeRange.at(0);
426 int rangeStart = mergeRange.at(1); 431 int rangeStart = mergeRange.at(1);
427 int rangeLen = mergeRange.at(2); 432 int rangeLen = mergeRange.at(2);
428 // XXX likely need somewhat similar to the code above:
429 // int blockInsPoint = rangeOrigin != csetMergeParent ? s1Start : p2MergeCommon.reverseMapLine(rangeStart);
430 //
431 ChangeBlockImpl block = getAddBlock(rangeStart, rangeLen, insPoint); 433 ChangeBlockImpl block = getAddBlock(rangeStart, rangeLen, insPoint);
432 block.setOriginAndTarget(rangeOrigin, csetTarget); 434 block.setOriginAndTarget(rangeOrigin, csetTarget);
435 if (rangeOrigin == csetMergeParent) {
436 block.setMergeFromLine(p2MergeCommon.getLineInP2(rangeStart));
437 }
433 insp.added(block); 438 insp.added(block);
434 // indicate insPoint moved down number of lines we just reported 439 // indicate insPoint moved down number of lines we just reported
435 insPoint += rangeLen; 440 insPoint += rangeLen;
436 } 441 }
437 } else { 442 } else {
448 protected void deleted(int s2DeletePoint, int s1From, int s1To) { 453 protected void deleted(int s2DeletePoint, int s1From, int s1To) {
449 if (shallStop()) { 454 if (shallStop()) {
450 return; 455 return;
451 } 456 }
452 try { 457 try {
453 ChangeBlockImpl block = new ChangeBlockImpl(annotatedRevision.origin, null, s1From, s1To - s1From, -1, -1, -1, s2DeletePoint); 458 ChangeBlockImpl block = getDeleteBlock(s1From, s1To - s1From, s2DeletePoint);
454 block.setOriginAndTarget(csetOrigin, csetTarget); 459 block.setOriginAndTarget(csetOrigin, csetTarget);
455 insp.deleted(block); 460 insp.deleted(block);
456 } catch (HgCallbackTargetException ex) { 461 } catch (HgCallbackTargetException ex) {
457 error = ex; 462 error = ex;
458 } 463 }
486 return new ChangeBlockImpl(null, annotatedRevision.target, -1, -1, start, len, insPoint, -1); 491 return new ChangeBlockImpl(null, annotatedRevision.target, -1, -1, start, len, insPoint, -1);
487 } 492 }
488 493
489 private ChangeBlockImpl getChangeBlock(int start1, int len1, int start2, int len2) { 494 private ChangeBlockImpl getChangeBlock(int start1, int len1, int start2, int len2) {
490 return new ChangeBlockImpl(annotatedRevision.origin, annotatedRevision.target, start1, len1, start2, len2, start1, start2); 495 return new ChangeBlockImpl(annotatedRevision.origin, annotatedRevision.target, start1, len1, start2, len2, start1, start2);
496 }
497
498 private ChangeBlockImpl getDeleteBlock(int start, int len, int delPoint) {
499 return new ChangeBlockImpl(annotatedRevision.origin, null, start, len, -1, -1, -1, delPoint);
491 } 500 }
492 } 501 }
493 502
494 private static class BlockImpl implements Block { 503 private static class BlockImpl implements Block {
495 private int originCset; 504 private int originCset;
558 private final int s2Start; 567 private final int s2Start;
559 private final int s2Len; 568 private final int s2Len;
560 private final int s1InsertPoint; 569 private final int s1InsertPoint;
561 private final int s2DeletePoint; 570 private final int s2DeletePoint;
562 private FilterBlock addedBlock, removedBlock; 571 private FilterBlock addedBlock, removedBlock;
572 private int mergedFromLine = -1;
563 573
564 public ChangeBlockImpl(ContentBlock c1, ContentBlock c2, int s1Start, int s1Len, int s2Start, int s2Len, int s1InsertPoint, int s2DeletePoint) { 574 public ChangeBlockImpl(ContentBlock c1, ContentBlock c2, int s1Start, int s1Len, int s2Start, int s2Len, int s1InsertPoint, int s2DeletePoint) {
565 oldContent = c1; 575 oldContent = c1;
566 newContent = c2; 576 newContent = c2;
567 this.s1Start = s1Start; 577 this.s1Start = s1Start;
573 } 583 }
574 584
575 public int insertedAt() { 585 public int insertedAt() {
576 return s1InsertPoint; 586 return s1InsertPoint;
577 } 587 }
588
589 public int mergeLineAt() {
590 return mergedFromLine;
591 }
578 592
579 public int firstAddedLine() { 593 public int firstAddedLine() {
580 return s2Start; 594 return s2Start;
581 } 595 }
582 596
617 } else if (s1InsertPoint == -1) { 631 } else if (s1InsertPoint == -1) {
618 // delete only 632 // delete only
619 return String.format("@@ -%d,%d +%d,0 @@", firstRemovedLine(), totalRemovedLines(), removedAt()); 633 return String.format("@@ -%d,%d +%d,0 @@", firstRemovedLine(), totalRemovedLines(), removedAt());
620 } 634 }
621 return String.format("@@ -%d,%d +%d,%d @@", firstRemovedLine(), totalRemovedLines(), firstAddedLine(), totalAddedLines()); 635 return String.format("@@ -%d,%d +%d,%d @@", firstRemovedLine(), totalRemovedLines(), firstAddedLine(), totalAddedLines());
636 }
637
638 void setMergeFromLine(int lineInOrigin) {
639 mergedFromLine = lineInOrigin;
622 } 640 }
623 } 641 }
624 642
625 private static class SingleLine implements BlockData { 643 private static class SingleLine implements BlockData {
626 private final ByteChain line; 644 private final ByteChain line;
730 * matching of [start1..end1) lines to lines in source1 and source2 748 * matching of [start1..end1) lines to lines in source1 and source2
731 * @return list of tuples (source, start, length), where source is one of the identifiers supplied 749 * @return list of tuples (source, start, length), where source is one of the identifiers supplied
732 */ 750 */
733 public IntSliceSeq combineAndMarkRangesWithSource(int start1, int end1, int start2, int end2, int source1, int source2); 751 public IntSliceSeq combineAndMarkRangesWithSource(int start1, int end1, int start2, int end2, int source1, int source2);
734 public IntSliceSeq combineAndMarkRangesWithSource(int insPoint, int start, int end, int source1, int source2); 752 public IntSliceSeq combineAndMarkRangesWithSource(int insPoint, int start, int end, int source1, int source2);
753 /**
754 * index in p2 of the mergeLine's origin in p2
755 */
735 public int getLineInP2(int mergeLine); 756 public int getLineInP2(int mergeLine);
736 } 757 }
737 758
738 // report lines as merged from p2 solely based on whether target line belongs 759 // report lines as merged from p2 solely based on whether target line belongs
739 // to a region that is equal to p2 region 760 // to a region that is equal to p2 region