diff src/org/tmatesoft/hg/internal/diff/DiffRangeMap.java @ 680:58a6900f845d

Blame: alternative strategy to handle merge revisions: map(diff(p1->base->p2)) to understand merge intentions better
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Sun, 21 Jul 2013 17:15:34 +0200
parents
children f568330dd9c0
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/org/tmatesoft/hg/internal/diff/DiffRangeMap.java	Sun Jul 21 17:15:34 2013 +0200
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2013 TMate Software Ltd
+ *  
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * For information on how to redistribute this software under
+ * the terms of a license other than GNU General Public License
+ * contact TMate Software at support@hg4j.com
+ */
+package org.tmatesoft.hg.internal.diff;
+
+import java.util.ArrayList;
+
+import org.tmatesoft.hg.internal.DiffHelper;
+import org.tmatesoft.hg.internal.IntSliceSeq;
+import org.tmatesoft.hg.internal.IntTuple;
+import org.tmatesoft.hg.internal.DiffHelper.ChunkSequence;
+
+/**
+ * Sequence of pairs of ranges (s1Start,s1End) - (s2Start, s2End)
+ * @author Artem Tikhomirov
+ * @author TMate Software Ltd.
+ */
+public class DiffRangeMap extends DiffHelper.DeltaInspector<ChunkSequence<?>> {
+	private final IntSliceSeq ranges;
+	
+	public DiffRangeMap() {
+		ranges = new IntSliceSeq(5);
+	}
+	
+	/**
+	 * handy method to fill this map from supplied DiffHelper
+	 * <pre>
+	 *   DiffHelper<LineSequence> pg = ...
+	 *   pg.findMatchingBlocks(p1ToBase); // doesn't compile
+	 *   DiffHelper<?> dh = pg;
+	 *   dh.findMatchingBlocks(p1ToBase); // compiles ok!
+	 * </pre>
+	 */
+	public DiffRangeMap fill(DiffHelper<?> dh) {
+		dh.findMatchingBlocks(this);
+		return this;
+	}
+	
+	@Override
+	protected void added(int s1InsertPoint, int s2From, int s2To) {
+		ranges.add(s1InsertPoint, s1InsertPoint, s2From, s2To, (int)'+');
+	}
+	@Override
+	protected void changed(int s1From, int s1To, int s2From, int s2To) {
+		ranges.add(s1From, s1To, s2From, s2To, (int)'*');
+	}
+	@Override
+	protected void deleted(int s2DeletePoint, int s1From, int s1To) {
+		ranges.add(s1From, s1To, s2DeletePoint, s2DeletePoint, (int)'-');
+	}
+	@Override
+	protected void unchanged(int s1From, int s2From, int length) {
+		ranges.add(s1From, s1From + length, s2From, s2From + length, (int)'=');
+	}
+
+	public Iterable<RangePair> findInSource(int sourceStart, int sourceEnd) {
+		ArrayList<RangePair> rv = new ArrayList<RangePair>(4); 
+		for (IntTuple t : ranges) {
+			int srcRangeStart = t.at(0);
+			int srcRangeEnd = t.at(1);
+			if (srcRangeEnd <= sourceStart) { // srcRangeEnd exclusive
+				continue;
+			}
+			if (srcRangeStart >= sourceEnd) {
+				break;
+			}
+			rv.add(new RangePair(srcRangeStart, srcRangeEnd, t.at(2), t.at(3)));
+		}
+		return rv;
+	}
+	
+	public Iterable<RangePair> insertions() {
+		return rangesOfKind('+');
+	}
+
+	public Iterable<RangePair> same() {
+		return rangesOfKind('=');
+	}
+
+	private Iterable<RangePair> rangesOfKind(int kind) {
+		ArrayList<RangePair> rv = new ArrayList<RangePair>(4); 
+		for (IntTuple t : ranges) {
+			if (t.at(4) == kind) {
+				rv.add(new RangePair(t.at(0), t.at(1), t.at(2), t.at(3)));
+			}
+		}
+		return rv;
+	}
+	
+	public static final class RangePair {
+		private final int s1Start;
+		private final int s1End;
+		private final int s2Start;
+		private final int s2End;
+
+		public RangePair(int s1Start, int s1End, int s2Start, int s2End) {
+			this.s1Start = s1Start;
+			this.s1End = s1End;
+			this.s2Start = s2Start;
+			this.s2End = s2End;
+		}
+		public int start1() {
+			return s1Start;
+		}
+		public int end1() {
+			return s1End;
+		}
+		public int length1() {
+			return s1End - s1Start;
+		}
+		public int start2() {
+			return s2Start;
+		}
+		public int end2() {
+			return s2End;
+		}
+		public int length2() {
+			return s2End - s2Start;
+		}
+		@Override
+		public String toString() {
+			return String.format("[%d..%d)->[%d..%d)", s1Start, s1End, s2Start, s2End);
+		}
+	}
+}