tikhomirov@542: /* tikhomirov@542: * Copyright (c) 2013 TMate Software Ltd tikhomirov@542: * tikhomirov@542: * This program is free software; you can redistribute it and/or modify tikhomirov@542: * it under the terms of the GNU General Public License as published by tikhomirov@542: * the Free Software Foundation; version 2 of the License. tikhomirov@542: * tikhomirov@542: * This program is distributed in the hope that it will be useful, tikhomirov@542: * but WITHOUT ANY WARRANTY; without even the implied warranty of tikhomirov@542: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the tikhomirov@542: * GNU General Public License for more details. tikhomirov@542: * tikhomirov@542: * For information on how to redistribute this software under tikhomirov@542: * the terms of a license other than GNU General Public License tikhomirov@542: * contact TMate Software at support@hg4j.com tikhomirov@542: */ tikhomirov@542: package org.tmatesoft.hg.test; tikhomirov@542: tikhomirov@543: import java.io.ByteArrayOutputStream; tikhomirov@543: import java.io.PrintStream; tikhomirov@543: import java.util.Arrays; tikhomirov@543: import java.util.regex.Pattern; tikhomirov@543: tikhomirov@543: import org.junit.Assert; tikhomirov@542: import org.junit.Test; tikhomirov@542: import org.tmatesoft.hg.internal.AnnotateFacility; tikhomirov@542: import org.tmatesoft.hg.internal.AnnotateFacility.AddBlock; tikhomirov@543: import org.tmatesoft.hg.internal.AnnotateFacility.Block; tikhomirov@542: import org.tmatesoft.hg.internal.AnnotateFacility.ChangeBlock; tikhomirov@542: import org.tmatesoft.hg.internal.AnnotateFacility.DeleteBlock; tikhomirov@542: import org.tmatesoft.hg.internal.IntMap; tikhomirov@542: import org.tmatesoft.hg.repo.HgDataFile; tikhomirov@542: import org.tmatesoft.hg.repo.HgLookup; tikhomirov@542: import org.tmatesoft.hg.repo.HgRepository; tikhomirov@542: tikhomirov@542: /** tikhomirov@542: * tikhomirov@542: * @author Artem Tikhomirov tikhomirov@542: * @author TMate Software Ltd. tikhomirov@542: */ tikhomirov@542: public class TestBlame { tikhomirov@542: tikhomirov@542: tikhomirov@542: @Test tikhomirov@542: public void testSingleParentBlame() throws Exception { tikhomirov@542: HgRepository repo = new HgLookup().detectFromWorkingDir(); tikhomirov@543: final String fname = "src/org/tmatesoft/hg/internal/PatchGenerator.java"; tikhomirov@543: final int checkChangeset = 539; tikhomirov@543: HgDataFile df = repo.getFileNode(fname); tikhomirov@543: ByteArrayOutputStream bos = new ByteArrayOutputStream(); tikhomirov@544: new AnnotateFacility().annotateChange(df, checkChangeset, new DiffOutInspector(new PrintStream(bos))); tikhomirov@543: LineGrepOutputParser gp = new LineGrepOutputParser("^@@.+"); tikhomirov@543: ExecHelper eh = new ExecHelper(gp, null); tikhomirov@543: eh.run("hg", "diff", "-c", String.valueOf(checkChangeset), "-U", "0", fname); tikhomirov@543: // tikhomirov@543: String[] apiResult = splitLines(bos.toString()); tikhomirov@543: String[] expected = splitLines(gp.result()); tikhomirov@543: Assert.assertArrayEquals(expected, apiResult); tikhomirov@543: } tikhomirov@543: tikhomirov@543: private static String[] splitLines(CharSequence seq) { tikhomirov@543: int lineCount = 0; tikhomirov@543: for (int i = 0, x = seq.length(); i < x; i++) { tikhomirov@543: if (seq.charAt(i) == '\n') { tikhomirov@543: lineCount++; tikhomirov@542: } tikhomirov@543: } tikhomirov@543: if (seq.length() > 0 && seq.charAt(seq.length()-1) != '\n') { tikhomirov@543: lineCount++; tikhomirov@543: } tikhomirov@543: String[] rv = new String[lineCount]; tikhomirov@543: int lineStart = 0, lineEnd = 0, ix = 0; tikhomirov@543: do { tikhomirov@543: while (lineEnd < seq.length() && seq.charAt(lineEnd) != '\n') lineEnd++; tikhomirov@543: if (lineEnd == lineStart) { tikhomirov@543: continue; tikhomirov@542: } tikhomirov@543: CharSequence line = seq.subSequence(lineStart, lineEnd); tikhomirov@543: rv[ix++] = line.toString(); tikhomirov@543: lineStart = ++lineEnd; tikhomirov@543: } while (lineStart < seq.length()); tikhomirov@543: assert ix == lineCount; tikhomirov@543: return rv; tikhomirov@543: } tikhomirov@543: tikhomirov@543: private void leftovers() { tikhomirov@543: IntMap linesOld = new IntMap(100), linesNew = new IntMap(100); tikhomirov@542: System.out.println("Changes to old revision:"); tikhomirov@542: for (int i = linesOld.firstKey(), x = linesOld.lastKey(); i < x; i++) { tikhomirov@542: if (linesOld.containsKey(i)) { tikhomirov@542: System.out.println(linesOld.get(i)); tikhomirov@542: } tikhomirov@542: } tikhomirov@542: tikhomirov@542: System.out.println("Changes in the new revision:"); tikhomirov@542: for (int i = linesNew.firstKey(), x = linesNew.lastKey(); i < x; i++) { tikhomirov@542: if (linesNew.containsKey(i)) { tikhomirov@542: System.out.println(linesNew.get(i)); tikhomirov@542: } tikhomirov@542: } tikhomirov@542: } tikhomirov@542: tikhomirov@542: public static void main(String[] args) throws Exception { tikhomirov@543: System.out.println(Arrays.equals(new String[0], splitLines(""))); tikhomirov@543: System.out.println(Arrays.equals(new String[] { "abc" }, splitLines("abc"))); tikhomirov@542: new TestBlame().testSingleParentBlame(); tikhomirov@542: } tikhomirov@543: tikhomirov@543: static class DiffOutInspector implements AnnotateFacility.Inspector { tikhomirov@543: private final PrintStream out; tikhomirov@543: tikhomirov@543: DiffOutInspector(PrintStream ps) { tikhomirov@543: out = ps; tikhomirov@543: } tikhomirov@543: tikhomirov@543: public void same(Block block) { tikhomirov@543: // nothing tikhomirov@543: } tikhomirov@543: tikhomirov@543: public void deleted(DeleteBlock block) { tikhomirov@543: out.printf("@@ -%d,%d +%d,0 @@\n", block.firstRemovedLine() + 1, block.totalRemovedLines(), block.removedAt()); tikhomirov@543: // String[] lines = block.removedLines(); tikhomirov@543: // assert lines.length == block.totalRemovedLines(); tikhomirov@543: // for (int i = 0, ln = block.firstRemovedLine(); i < lines.length; i++, ln++) { tikhomirov@543: // linesOld.put(ln, String.format("%3d:---:%s", ln, lines[i])); tikhomirov@543: // } tikhomirov@543: } tikhomirov@543: tikhomirov@543: public void changed(ChangeBlock block) { tikhomirov@543: // deleted(block); tikhomirov@543: // added(block); tikhomirov@543: out.printf("@@ -%d,%d +%d,%d @@\n", block.firstRemovedLine() + 1, block.totalRemovedLines(), block.firstAddedLine() + 1, block.totalAddedLines()); tikhomirov@543: } tikhomirov@543: tikhomirov@543: public void added(AddBlock block) { tikhomirov@543: out.printf("@@ -%d,0 +%d,%d @@\n", block.insertedAt(), block.firstAddedLine() + 1, block.totalAddedLines()); tikhomirov@543: // String[] addedLines = block.addedLines(); tikhomirov@543: // assert addedLines.length == block.totalAddedLines(); tikhomirov@543: // for (int i = 0, ln = block.firstAddedLine(), x = addedLines.length; i < x; i++, ln++) { tikhomirov@543: // linesNew.put(ln, String.format("%3d:+++:%s", ln, addedLines[i])); tikhomirov@543: // } tikhomirov@543: } tikhomirov@543: } tikhomirov@543: tikhomirov@543: public static class LineGrepOutputParser implements OutputParser { tikhomirov@543: tikhomirov@543: private final Pattern pattern; tikhomirov@543: private final StringBuilder result = new StringBuilder(); tikhomirov@543: tikhomirov@543: public LineGrepOutputParser(String regexp) { tikhomirov@543: pattern = Pattern.compile(regexp); tikhomirov@543: } tikhomirov@543: tikhomirov@543: public CharSequence result() { tikhomirov@543: return result; tikhomirov@543: } tikhomirov@543: tikhomirov@543: public void parse(CharSequence seq) { tikhomirov@543: int lineStart = 0, lineEnd = 0; tikhomirov@543: do { tikhomirov@543: while (lineEnd < seq.length() && seq.charAt(lineEnd) != '\n') lineEnd++; tikhomirov@543: if (lineEnd == lineStart) { tikhomirov@543: continue; tikhomirov@543: } tikhomirov@543: CharSequence line = seq.subSequence(lineStart, lineEnd); tikhomirov@543: if (pattern.matcher(line).matches()) { tikhomirov@543: result.append(line); tikhomirov@543: result.append('\n'); tikhomirov@543: } tikhomirov@543: lineStart = ++lineEnd; tikhomirov@543: } while (lineStart < seq.length()); tikhomirov@543: } tikhomirov@543: } tikhomirov@542: }