comparison test/org/tmatesoft/hg/test/TestBlame.java @ 677:1c49c0cee540

Report line number at the first appearance, like 'hg annotate -l' does
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Thu, 18 Jul 2013 18:47:45 +0200
parents 3219cfadda49
children 58a6900f845d
comparison
equal deleted inserted replaced
676:3219cfadda49 677:1c49c0cee540
29 import java.io.PrintStream; 29 import java.io.PrintStream;
30 import java.util.ArrayList; 30 import java.util.ArrayList;
31 import java.util.Arrays; 31 import java.util.Arrays;
32 import java.util.LinkedHashSet; 32 import java.util.LinkedHashSet;
33 import java.util.LinkedList; 33 import java.util.LinkedList;
34 import java.util.List;
35 import java.util.ListIterator; 34 import java.util.ListIterator;
36 import java.util.regex.Matcher; 35 import java.util.regex.Matcher;
37 import java.util.regex.Pattern; 36 import java.util.regex.Pattern;
38 37
39 import org.junit.Assert; 38 import org.junit.Assert;
106 ar.run(cs, false); 105 ar.run(cs, false);
107 diffCmd.range(0, cs); 106 diffCmd.range(0, cs);
108 final ReverseAnnotateInspector insp = new ReverseAnnotateInspector(); 107 final ReverseAnnotateInspector insp = new ReverseAnnotateInspector();
109 diffCmd.executeAnnotate(insp); 108 diffCmd.executeAnnotate(insp);
110 AnnotateInspector fa = new AnnotateInspector().fill(cs, insp); 109 AnnotateInspector fa = new AnnotateInspector().fill(cs, insp);
111 doAnnotateLineCheck(cs, ar.getLines(), fa.changesets, fa.lines); 110 doAnnotateLineCheck(cs, ar, fa);
112 } 111 }
113 } 112 }
114 113
115 @Test 114 @Test
116 public void testFileLineAnnotate2() throws Exception { 115 public void testFileLineAnnotate2() throws Exception {
123 ar.run(cs, false); 122 ar.run(cs, false);
124 diffCmd.range(0, cs); 123 diffCmd.range(0, cs);
125 final ReverseAnnotateInspector insp = new ReverseAnnotateInspector(); 124 final ReverseAnnotateInspector insp = new ReverseAnnotateInspector();
126 diffCmd.executeAnnotate(insp); 125 diffCmd.executeAnnotate(insp);
127 AnnotateInspector fa = new AnnotateInspector().fill(cs, insp); 126 AnnotateInspector fa = new AnnotateInspector().fill(cs, insp);
128 doAnnotateLineCheck(cs, ar.getLines(), fa.changesets, fa.lines); 127 doAnnotateLineCheck(cs, ar, fa);
129 } 128 }
130 /*`hg annotate -r 8` and HgBlameFacility give different result 129 /*`hg annotate -r 8` and HgBlameFacility give different result
131 * for "r0, line 5" line, which was deleted in rev2 and restored back in 130 * for "r0, line 5" line, which was deleted in rev2 and restored back in
132 * rev4 (both in default branch), while branch with r3 and r6 kept the line intact. 131 * rev4 (both in default branch), while branch with r3 and r6 kept the line intact.
133 * HgBlame reports rev4 for the line, `hg annotate` gives original, rev0. 132 * HgBlame reports rev4 for the line, `hg annotate` gives original, rev0.
251 // follow 250 // follow
252 cmd.file(fname); 251 cmd.file(fname);
253 cmd.execute(ai); 252 cmd.execute(ai);
254 AnnotateRunner ar = new AnnotateRunner(fname, repo.getWorkingDir()); 253 AnnotateRunner ar = new AnnotateRunner(fname, repo.getWorkingDir());
255 ar.run(changeset, true); 254 ar.run(changeset, true);
256 doAnnotateLineCheck(changeset, ar.getLines(), ai.changesets, ai.lines); 255 doAnnotateLineCheck(changeset, ar, ai);
257 256
258 // no follow 257 // no follow
259 cmd.file(fname, false); 258 cmd.file(fname, false);
260 ai = new AnnotateInspector(); 259 ai = new AnnotateInspector();
261 cmd.execute(ai); 260 cmd.execute(ai);
262 ar.run(changeset, false); 261 ar.run(changeset, false);
263 doAnnotateLineCheck(changeset, ar.getLines(), ai.changesets, ai.lines); 262 doAnnotateLineCheck(changeset, ar, ai);
264 } 263 }
265 264
266 // FIXME add originLineNumber to HgAnnotateCommand#LineInfo, pass it from FileAnnotate, test 265 private void doAnnotateLineCheck(int cs, AnnotateRunner ar, AnnotateInspector hg4jResult) {
267 266 String[] hgAnnotateLines = ar.getLines();
268 private void doAnnotateLineCheck(int cs, String[] hgAnnotateLines, List<Integer> cmdChangesets, List<String> cmdLines) {
269 assertTrue("[sanity]", hgAnnotateLines.length > 0); 267 assertTrue("[sanity]", hgAnnotateLines.length > 0);
270 assertEquals("Number of lines reported by native annotate and our impl", hgAnnotateLines.length, cmdLines.size()); 268 assertEquals("Number of lines reported by native annotate and our impl", hgAnnotateLines.length, hg4jResult.getLineCount());
271 269
272 for (int i = 0; i < cmdChangesets.size(); i++) { 270 for (int i = 0; i < hgAnnotateLines.length; i++) {
273 int hgAnnotateRevIndex = Integer.parseInt(hgAnnotateLines[i].substring(0, hgAnnotateLines[i].indexOf(':')).trim()); 271 String[] hgLine = hgAnnotateLines[i].split(":");
274 errorCollector.assertEquals(String.format("Revision mismatch for line %d (annotating rev: %d)", i+1, cs), hgAnnotateRevIndex, cmdChangesets.get(i)); 272 assertTrue(hgAnnotateLines[i], hgLine.length >= 3);
275 String hgAnnotateLine = hgAnnotateLines[i].substring(hgAnnotateLines[i].indexOf(':') + 1); 273 int hgAnnotateRevIndex = Integer.parseInt(hgLine[0].trim());
276 String apiLine = cmdLines.get(i).trim(); 274 int hgFirstAppLine = Integer.parseInt(hgLine[1].trim());
277 errorCollector.assertEquals(hgAnnotateLine.trim(), apiLine); 275 String hgLineText = hgAnnotateLines[i].substring(hgLine[0].length() + hgLine[1].length() + 2).trim();
276 errorCollector.assertEquals(String.format("Revision mismatch for line %d (annotating rev: %d)", i+1, cs), hgAnnotateRevIndex, hg4jResult.getChangeset(i));
277 errorCollector.assertEquals(hgLineText, hg4jResult.getLine(i).trim());
278 errorCollector.assertEquals(hgFirstAppLine, hg4jResult.getOriginLine(i));
278 } 279 }
279 } 280 }
280 281
281 282
282 @Test 283 @Test
523 System.out.printf("%3d:%s:[%d..%d):\n%s", cset, marker, first, first+length, content); 524 System.out.printf("%3d:%s:[%d..%d):\n%s", cset, marker, first, first+length, content);
524 } 525 }
525 } 526 }
526 } 527 }
527 528
529 /**
530 * Note, this class expects lines coming in natural sequence (not the order they are detected - possible with {@link ReverseAnnotateInspector})
531 * Once async lines are done, shall change implementation here
532 */
528 static class AnnotateInspector implements HgAnnotateCommand.Inspector { 533 static class AnnotateInspector implements HgAnnotateCommand.Inspector {
529 private int lineNumber = 1; 534 private int lineNumber = 1;
530 public final ArrayList<String> lines = new ArrayList<String>(); 535 private final ArrayList<String> lines = new ArrayList<String>();
531 public final ArrayList<Integer> changesets = new ArrayList<Integer>(); 536 private final IntVector changesets = new IntVector();
537 private final IntVector firstAppLines = new IntVector();
532 538
533 AnnotateInspector fill(int rev, ReverseAnnotateInspector ai) throws HgCallbackTargetException, CancelledException { 539 AnnotateInspector fill(int rev, ReverseAnnotateInspector ai) throws HgCallbackTargetException, CancelledException {
534 ai.report(rev, this, ProgressSupport.Factory.get(null), CancelSupport.Factory.get(null)); 540 ai.report(rev, this, ProgressSupport.Factory.get(null), CancelSupport.Factory.get(null));
535 return this; 541 return this;
536 } 542 }
542 public void next(LineInfo lineInfo) throws HgCallbackTargetException { 548 public void next(LineInfo lineInfo) throws HgCallbackTargetException {
543 Assert.assertEquals(lineInfo.getLineNumber(), lineNumber); 549 Assert.assertEquals(lineInfo.getLineNumber(), lineNumber);
544 lineNumber++; 550 lineNumber++;
545 lines.add(new String(lineInfo.getContent())); 551 lines.add(new String(lineInfo.getContent()));
546 changesets.add(lineInfo.getChangesetIndex()); 552 changesets.add(lineInfo.getChangesetIndex());
553 firstAppLines.add(lineInfo.getOriginLineNumber());
554 }
555
556 int getLineCount() {
557 return changesets.size();
558 }
559 int getChangeset(int line) {
560 return changesets.get(line);
561 }
562 String getLine(int line) {
563 return lines.get(line);
564 }
565 int getOriginLine(int line) {
566 return firstAppLines.get(line);
547 } 567 }
548 } 568 }
549 569
550 private static class AnnotateRunner { 570 private static class AnnotateRunner {
551 private final ExecHelper eh; 571 private final ExecHelper eh;
561 public void run(int cset, boolean follow) throws Exception { 581 public void run(int cset, boolean follow) throws Exception {
562 op.reset(); 582 op.reset();
563 ArrayList<String> args = new ArrayList<String>(); 583 ArrayList<String> args = new ArrayList<String>();
564 args.add("hg"); 584 args.add("hg");
565 args.add("annotate"); 585 args.add("annotate");
586 args.add("--line-number");
566 args.add("-r"); 587 args.add("-r");
567 args.add(cset == TIP ? "tip" : String.valueOf(cset)); 588 args.add(cset == TIP ? "tip" : String.valueOf(cset));
568 if (!follow) { 589 if (!follow) {
569 args.add("--no-follow"); 590 args.add("--no-follow");
570 } 591 }