Mercurial > hg4j
diff test/org/tmatesoft/hg/test/TestBlame.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/test/org/tmatesoft/hg/test/TestBlame.java Fri Feb 22 20:21:24 2013 +0100 +++ b/test/org/tmatesoft/hg/test/TestBlame.java Sun Feb 24 00:11:40 2013 +0100 @@ -22,10 +22,13 @@ import static org.tmatesoft.hg.repo.HgRepository.TIP; import java.io.ByteArrayOutputStream; +import java.io.IOException; import java.io.PrintStream; import java.util.Arrays; import java.util.LinkedHashSet; import java.util.LinkedList; +import java.util.ListIterator; +import java.util.regex.Matcher; import java.util.regex.Pattern; import org.junit.Assert; @@ -37,15 +40,15 @@ import org.tmatesoft.hg.internal.FileAnnotation.LineInspector; import org.tmatesoft.hg.internal.IntVector; import org.tmatesoft.hg.repo.HgBlameFacility; -import org.tmatesoft.hg.repo.HgDataFile; -import org.tmatesoft.hg.repo.HgLookup; -import org.tmatesoft.hg.repo.HgRepository; import org.tmatesoft.hg.repo.HgBlameFacility.AddBlock; import org.tmatesoft.hg.repo.HgBlameFacility.Block; import org.tmatesoft.hg.repo.HgBlameFacility.BlockData; import org.tmatesoft.hg.repo.HgBlameFacility.ChangeBlock; import org.tmatesoft.hg.repo.HgBlameFacility.DeleteBlock; import org.tmatesoft.hg.repo.HgBlameFacility.EqualBlock; +import org.tmatesoft.hg.repo.HgDataFile; +import org.tmatesoft.hg.repo.HgLookup; +import org.tmatesoft.hg.repo.HgRepository; /** * @@ -56,6 +59,7 @@ @Rule public ErrorCollectorExt errorCollector = new ErrorCollectorExt(); + private ExecHelper eh; @Test @@ -76,29 +80,46 @@ } @Test - public void testFileAnnotate() throws Exception { + public void testFileLineAnnotate1() throws Exception { HgRepository repo = new HgLookup().detectFromWorkingDir(); final String fname = "src/org/tmatesoft/hg/internal/PatchGenerator.java"; HgDataFile df = repo.getFileNode(fname); OutputParser.Stub op = new OutputParser.Stub(); - ExecHelper eh = new ExecHelper(op, null); + eh = new ExecHelper(op, null); for (int startChangeset : new int[] { 539, 541 /*, TIP */}) { - FileAnnotateInspector fa = new FileAnnotateInspector(); - FileAnnotation.annotate(df, startChangeset, fa); - + doLineAnnotateTest(df, startChangeset, op); + } + } + + private void doLineAnnotateTest(HgDataFile df, int cs, OutputParser.Stub op) throws InterruptedException, IOException { + FileAnnotateInspector fa = new FileAnnotateInspector(); + FileAnnotation.annotate(df, cs, fa); - op.reset(); - eh.run("hg", "annotate", "-r", startChangeset == TIP ? "tip" : String.valueOf(startChangeset), fname); - - String[] hgAnnotateLines = splitLines(op.result()); - assertTrue("[sanity]", hgAnnotateLines.length > 0); - assertEquals("Number of lines reported by native annotate and our impl", hgAnnotateLines.length, fa.lineRevisions.length); + op.reset(); + eh.run("hg", "annotate", "-r", cs == TIP ? "tip" : String.valueOf(cs), df.getPath().toString()); + + String[] hgAnnotateLines = splitLines(op.result()); + assertTrue("[sanity]", hgAnnotateLines.length > 0); + assertEquals("Number of lines reported by native annotate and our impl", hgAnnotateLines.length, fa.lineRevisions.length); + + for (int i = 0; i < fa.lineRevisions.length; i++) { + int hgAnnotateRevIndex = Integer.parseInt(hgAnnotateLines[i].substring(0, hgAnnotateLines[i].indexOf(':'))); + errorCollector.assertEquals(String.format("Revision mismatch for line %d", i+1), hgAnnotateRevIndex, fa.lineRevisions[i]); + String hgAnnotateLine = hgAnnotateLines[i].substring(hgAnnotateLines[i].indexOf(':') + 1); + String apiLine = fa.line(i).trim(); + errorCollector.assertEquals(hgAnnotateLine.trim(), apiLine); + } + } - for (int i = 0; i < fa.lineRevisions.length; i++) { - int hgAnnotateRevIndex = Integer.parseInt(hgAnnotateLines[i].substring(0, hgAnnotateLines[i].indexOf(':'))); - errorCollector.assertEquals(String.format("Revision mismatch for line %d", i+1), hgAnnotateRevIndex, fa.lineRevisions[i]); - } + @Test + public void testFileLineAnnotate2() throws Exception { + HgRepository repo = Configuration.get().find("test-annotate"); + HgDataFile df = repo.getFileNode("file1"); + OutputParser.Stub op = new OutputParser.Stub(); + eh = new ExecHelper(op, repo.getWorkingDir()); + for (int cs : new int[] { 4, 6, TIP/*, 8 FIXME find out how come hg annotate doesn't see re-added line in rev4*/}) { + doLineAnnotateTest(df, cs, op); } } @@ -112,6 +133,41 @@ af.annotate(df, TIP, dump, HgIterateDirection.OldToNew); LinkedList<String> apiResult = new LinkedList<String>(Arrays.asList(splitLines(bos.toString()))); + /* + * FIXME this is an ugly hack to deal with the way `hg diff -c <mergeRev>` describes the change + * and our merge handling approach. For merged revision m, and lines changed both in p1 and p2 + * we report lines from p2 as pure additions, regardless of intersecting p1 changes (which + * are reported as deletions, if no sufficient changed lines in m found) + * So, here we try to combine deletion that follows a change (based on identical insertionPoint) + * into a single change + * To fix, need to find better approach to find out reference info (i.e. `hg diff -c` is flawed in this case, + * as it uses first parent only). + */ + Pattern fix = Pattern.compile("@@ -(\\d+),(\\d+) \\+(\\d+),(\\d+) @@"); + int v1, v2, v3, v4; + v1 = v2 = v3 = v4 = -1; + for (ListIterator<String> it = apiResult.listIterator(); it.hasNext();) { + String n = it.next(); + Matcher m = fix.matcher(n); + if (m.find()) { + int d1 = Integer.parseInt(m.group(1)); + int d2 = Integer.parseInt(m.group(2)); + int d3 = Integer.parseInt(m.group(3)); + int d4 = Integer.parseInt(m.group(4)); + if (v1 == d1 && d4 == 0) { + it.previous(); // shift to current element + it.previous(); // to real previous + it.remove(); + it.next(); + it.set(String.format("@@ -%d,%d +%d,%d @@", v1, v2+d2, v3, v4)); + } + v1 = d1; + v2 = d2; + v3 = d3; + v4 = d4; + } + } + LineGrepOutputParser gp = new LineGrepOutputParser("^@@.+"); ExecHelper eh = new ExecHelper(gp, repo.getWorkingDir()); for (int cs : dump.getReportedTargetRevisions()) { @@ -199,18 +255,18 @@ HgRepository repo = new HgLookup().detect("/home/artem/hg/junit-test-repos/test-annotate/"); HgDataFile df = repo.getFileNode("file1"); HgBlameFacility af = new HgBlameFacility(); - DiffOutInspector dump = new DiffOutInspector(System.out); - dump.needRevisions(true); - af.annotate(df, TIP, dump, HgIterateDirection.OldToNew); - System.out.println(); - af.annotate(df, TIP, new LineDumpInspector(true), HgIterateDirection.NewToOld); - System.out.println(); - af.annotate(df, TIP, new LineDumpInspector(false), HgIterateDirection.NewToOld); - System.out.println(); +// DiffOutInspector dump = new DiffOutInspector(System.out); +// dump.needRevisions(true); +// af.annotate(df, TIP, dump, HgIterateDirection.OldToNew); +// System.out.println(); +// af.annotate(df, TIP, new LineDumpInspector(true), HgIterateDirection.NewToOld); +// System.out.println(); +// af.annotate(df, TIP, new LineDumpInspector(false), HgIterateDirection.NewToOld); +// System.out.println(); FileAnnotateInspector fa = new FileAnnotateInspector(); - FileAnnotation.annotate(df, TIP, fa); + FileAnnotation.annotate(df, TIP, fa); //4,6,TIP for (int i = 0; i < fa.lineRevisions.length; i++) { - System.out.printf("%d: LINE %d\n", fa.lineRevisions[i], i+1); + System.out.printf("%d: %s", fa.lineRevisions[i], fa.line(i) == null ? "null\n" : fa.line(i)); } } @@ -312,16 +368,23 @@ private static class FileAnnotateInspector implements LineInspector { private int[] lineRevisions; + private String[] lines; FileAnnotateInspector() { } - public void line(int lineNumber, int changesetRevIndex, LineDescriptor ld) { + public void line(int lineNumber, int changesetRevIndex, BlockData lineContent, LineDescriptor ld) { if (lineRevisions == null) { lineRevisions = new int [ld.totalLines()]; Arrays.fill(lineRevisions, NO_REVISION); + lines = new String[ld.totalLines()]; } lineRevisions[lineNumber] = changesetRevIndex; + lines[lineNumber] = new String(lineContent.asArray()); + } + + public String line(int i) { + return lines[i]; } }