diff src/org/tmatesoft/hg/repo/HgBlameFacility.java @ 557:b9e5ac26dd83

Annotate: Line annotation needs true line position from merged blocks; test-annotate repo updated to show elements from both parents in the merged revision
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Sun, 24 Feb 2013 00:11:40 +0100
parents e55f17a7a195
children 154718ae23ed
line wrap: on
line diff
--- a/src/org/tmatesoft/hg/repo/HgBlameFacility.java	Fri Feb 22 20:21:24 2013 +0100
+++ b/src/org/tmatesoft/hg/repo/HgBlameFacility.java	Sun Feb 24 00:11:40 2013 +0100
@@ -442,12 +442,15 @@
 				p2MergeCommon.combineAndMarkRangesWithTarget(s2From, s2To - s2From, csetOrigin, csetMergeParent, mergeRanges);
 				
 				/*
-				 * Usecases:
+				 * Usecases, how it USED TO BE initially:
 				 * 3 lines changed to 10 lines. range of 10 lines breaks down to 2 from p2, 3 from p1, and 5 from p2.
 				 * We report: 2 lines changed to 2(p2), then 1 line changed with 3(p1) and 5 lines added from p2.
 				 * 
 				 * 10 lines changed to 3 lines, range of 3 lines breaks down to 2 line from p1 and 1 line from p2.
-				 * We report: 2 lines changed to 2(p1) and 8 lines changed to 1(p2) 
+				 * We report: 2 lines changed to 2(p1) and 8 lines changed to 1(p2)
+				 * 
+				 * NOW, lines from p2 are always reported as pure add (since we need their insertion point to be in p2, not in p1)
+				 * and we try to consume p1 changes as soon as we see first p1's range 
 				 */
 				int s1TotalLines = s1To - s1From, s1ConsumedLines = 0, s1Start = s1From;
 				
@@ -457,22 +460,30 @@
 					final int rangeLen = mergeRanges.get(i+2);
 					final boolean lastRange = i+3 >= mergeRanges.size();
 					final int s1LinesLeft = s1TotalLines - s1ConsumedLines;
-					// how many lines we may reported as changed (don't use more than in range unless it's the very last range)
+					// how many lines we may report as changed (don't use more than in range unless it's the very last range)
 					final int s1LinesToBorrow = lastRange ? s1LinesLeft : Math.min(s1LinesLeft, rangeLen);
-					if (s1LinesToBorrow > 0) {
+					if (rangeOrigin != csetMergeParent && s1LinesToBorrow > 0) {
 						ChangeBlockImpl block = getChangeBlock(s1Start, s1LinesToBorrow, rangeStart, rangeLen);
 						block.setOriginAndTarget(rangeOrigin, csetTarget);
 						insp.changed(block);
 						s1ConsumedLines += s1LinesToBorrow;
 						s1Start += s1LinesToBorrow;
 					} else {
-						ChangeBlockImpl block = getAddBlock(rangeStart, rangeLen, s1Start);
+						int blockInsPoint = rangeOrigin != csetMergeParent ? s1Start : p2MergeCommon.reverseMapLine(rangeStart);
+						ChangeBlockImpl block = getAddBlock(rangeStart, rangeLen, blockInsPoint);
 						block.setOriginAndTarget(rangeOrigin, csetTarget);
 						insp.added(block);
 					}
 				}
 				if (s1ConsumedLines != s1TotalLines) {
-					throw new HgInvalidStateException(String.format("Expected to process %d lines, but actually was %d", s1TotalLines, s1ConsumedLines));
+					assert s1ConsumedLines < s1TotalLines : String.format("Expected to process %d lines, but actually was %d", s1TotalLines, s1ConsumedLines);
+					// either there were no ranges from p1, whole s2From..s2To range came from p2, shall report as deleted
+					// or the ranges found were not enough to consume whole s2From..s2To
+					// The "deletion point" is shifted to the end of last csetOrigin->csetTarget change
+					int s2DeletePoint = s2From + s1ConsumedLines;
+					ChangeBlockImpl block =  new ChangeBlockImpl(annotatedRevision.origin, null, s1Start, s1To - s1Start, -1, -1, -1, s2DeletePoint);
+					block.setOriginAndTarget(csetOrigin, csetTarget);
+					insp.deleted(block);
 				}
 			} else {
 				ChangeBlockImpl block = getChangeBlock(s1From, s1To - s1From, s2From, s2To - s2From);
@@ -730,6 +741,7 @@
 	
 
 	static class EqualBlocksCollector implements DiffHelper.MatchInspector<LineSequence> {
+		// FIXME replace with RangeSeq
 		private final IntVector matches = new IntVector(10*3, 2*3);
 
 		public void begin(LineSequence s1, LineSequence s2) {
@@ -771,6 +783,25 @@
 			}
 		}
 		
+		/**
+		 * find out line index in origin that matches specifid target line
+		 */
+		public int reverseMapLine(int targetLine) {
+			for (int i = 0; i < matches.size(); i +=3) {
+				int os = matches.get(i);
+				int ts = matches.get(i + 1);
+				int l = matches.get(i + 2);
+				if (ts > targetLine) {
+					return -1;
+				}
+				if (ts + l > targetLine) {
+					return os + (targetLine - ts);
+				}
+			}
+			return -1;
+		}
+
+
 		/*
 		 * intersects [start..start+length) with ranges of target lines, and based on the intersection 
 		 * breaks initial range into smaller ranges and records them into result, with marker to indicate
@@ -877,6 +908,13 @@
 		public int fileRevisionIndex() {
 			return fileRevIndex;
 		}
+		@Override
+		public String toString() {
+			if (isMerge()) {
+				return String.format("[%d,%d->%d]", originCset, mergeCset, targetCset);
+			}
+			return String.format("[%d->%d]", originCset, targetCset);
+		}
 	}
 
 	public static void main(String[] args) {