Mercurial > hg4j
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); + } + } +}