comparison test/org/tmatesoft/hg/test/TestBlame.java @ 676:3219cfadda49

Switch to alternative annotate producer (walks from parents to children). Refactor FileAnnotation to match updated annotate approach
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Thu, 18 Jul 2013 18:03:51 +0200
parents 54e16ab771ec
children 1c49c0cee540
comparison
equal deleted inserted replaced
675:a20121a2bba6 676:3219cfadda49
18 18
19 import static org.junit.Assert.assertEquals; 19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertTrue; 20 import static org.junit.Assert.assertTrue;
21 import static org.tmatesoft.hg.core.HgIterateDirection.NewToOld; 21 import static org.tmatesoft.hg.core.HgIterateDirection.NewToOld;
22 import static org.tmatesoft.hg.core.HgIterateDirection.OldToNew; 22 import static org.tmatesoft.hg.core.HgIterateDirection.OldToNew;
23 import static org.tmatesoft.hg.repo.HgRepository.NO_REVISION;
24 import static org.tmatesoft.hg.repo.HgRepository.TIP; 23 import static org.tmatesoft.hg.repo.HgRepository.TIP;
25 24
26 import java.io.ByteArrayOutputStream; 25 import java.io.ByteArrayOutputStream;
27 import java.io.File; 26 import java.io.File;
28 import java.io.IOException; 27 import java.io.IOException;
45 import org.tmatesoft.hg.core.HgBlameInspector; 44 import org.tmatesoft.hg.core.HgBlameInspector;
46 import org.tmatesoft.hg.core.HgCallbackTargetException; 45 import org.tmatesoft.hg.core.HgCallbackTargetException;
47 import org.tmatesoft.hg.core.HgDiffCommand; 46 import org.tmatesoft.hg.core.HgDiffCommand;
48 import org.tmatesoft.hg.core.HgRepoFacade; 47 import org.tmatesoft.hg.core.HgRepoFacade;
49 import org.tmatesoft.hg.core.Nodeid; 48 import org.tmatesoft.hg.core.Nodeid;
50 import org.tmatesoft.hg.internal.FileAnnotation; 49 import org.tmatesoft.hg.internal.ForwardAnnotateInspector;
51 import org.tmatesoft.hg.internal.FileAnnotation.LineDescriptor;
52 import org.tmatesoft.hg.internal.FileAnnotation.LineInspector;
53 import org.tmatesoft.hg.internal.IntVector; 50 import org.tmatesoft.hg.internal.IntVector;
51 import org.tmatesoft.hg.internal.ReverseAnnotateInspector;
54 import org.tmatesoft.hg.repo.HgChangelog; 52 import org.tmatesoft.hg.repo.HgChangelog;
55 import org.tmatesoft.hg.repo.HgDataFile; 53 import org.tmatesoft.hg.repo.HgDataFile;
56 import org.tmatesoft.hg.repo.HgLookup; 54 import org.tmatesoft.hg.repo.HgLookup;
57 import org.tmatesoft.hg.repo.HgRepository; 55 import org.tmatesoft.hg.repo.HgRepository;
56 import org.tmatesoft.hg.util.CancelSupport;
57 import org.tmatesoft.hg.util.CancelledException;
58 import org.tmatesoft.hg.util.Path; 58 import org.tmatesoft.hg.util.Path;
59 import org.tmatesoft.hg.util.ProgressSupport;
59 60
60 /** 61 /**
61 * 62 *
62 * @author Artem Tikhomirov 63 * @author Artem Tikhomirov
63 * @author TMate Software Ltd. 64 * @author TMate Software Ltd.
101 clog.getRevisionIndex(Nodeid.fromAscii("946b131962521f9199e1fedbdc2487d3aaef5e46")), // 539 102 clog.getRevisionIndex(Nodeid.fromAscii("946b131962521f9199e1fedbdc2487d3aaef5e46")), // 539
102 clog.getRevisionIndex(Nodeid.fromAscii("1e95f48d9886abe79b9711ab371bc877ca5e773e")), // 541 103 clog.getRevisionIndex(Nodeid.fromAscii("1e95f48d9886abe79b9711ab371bc877ca5e773e")), // 541
103 /*, TIP */}; 104 /*, TIP */};
104 for (int cs : toTest) { 105 for (int cs : toTest) {
105 ar.run(cs, false); 106 ar.run(cs, false);
106 FileAnnotateInspector fa = new FileAnnotateInspector();
107 diffCmd.range(0, cs); 107 diffCmd.range(0, cs);
108 diffCmd.executeAnnotate(new FileAnnotation(fa)); 108 final ReverseAnnotateInspector insp = new ReverseAnnotateInspector();
109 doAnnotateLineCheck(cs, ar.getLines(), Arrays.asList(fa.lineRevisions), Arrays.asList(fa.lines)); 109 diffCmd.executeAnnotate(insp);
110 AnnotateInspector fa = new AnnotateInspector().fill(cs, insp);
111 doAnnotateLineCheck(cs, ar.getLines(), fa.changesets, fa.lines);
110 } 112 }
111 } 113 }
112 114
113 @Test 115 @Test
114 public void testFileLineAnnotate2() throws Exception { 116 public void testFileLineAnnotate2() throws Exception {
117 AnnotateRunner ar = new AnnotateRunner(df.getPath(), repo.getWorkingDir()); 119 AnnotateRunner ar = new AnnotateRunner(df.getPath(), repo.getWorkingDir());
118 120
119 final HgDiffCommand diffCmd = new HgDiffCommand(repo).file(df).order(NewToOld); 121 final HgDiffCommand diffCmd = new HgDiffCommand(repo).file(df).order(NewToOld);
120 for (int cs : new int[] { 4, 6 /*, 8 see below*/, TIP}) { 122 for (int cs : new int[] { 4, 6 /*, 8 see below*/, TIP}) {
121 ar.run(cs, false); 123 ar.run(cs, false);
122 FileAnnotateInspector fa = new FileAnnotateInspector();
123 diffCmd.range(0, cs); 124 diffCmd.range(0, cs);
124 diffCmd.executeAnnotate(new FileAnnotation(fa)); 125 final ReverseAnnotateInspector insp = new ReverseAnnotateInspector();
125 doAnnotateLineCheck(cs, ar.getLines(), Arrays.asList(fa.lineRevisions), Arrays.asList(fa.lines)); 126 diffCmd.executeAnnotate(insp);
127 AnnotateInspector fa = new AnnotateInspector().fill(cs, insp);
128 doAnnotateLineCheck(cs, ar.getLines(), fa.changesets, fa.lines);
126 } 129 }
127 /*`hg annotate -r 8` and HgBlameFacility give different result 130 /*`hg annotate -r 8` and HgBlameFacility give different result
128 * for "r0, line 5" line, which was deleted in rev2 and restored back in 131 * for "r0, line 5" line, which was deleted in rev2 and restored back in
129 * rev4 (both in default branch), while branch with r3 and r6 kept the line intact. 132 * rev4 (both in default branch), while branch with r3 and r6 kept the line intact.
130 * HgBlame reports rev4 for the line, `hg annotate` gives original, rev0. 133 * HgBlame reports rev4 for the line, `hg annotate` gives original, rev0.
131 * However `hg annotate -r 4` shows rev4 for the line, too. The aforementioned rev0 for 134 * However `hg annotate -r 4` shows rev4 for the line, too. The aforementioned rev0 for
132 * the merge rev8 results from the iteration order and is implementation specific 135 * the merge rev8 results from the iteration order and is implementation specific
133 * (i.e. one can't tell which one is right). Mercurial walks from parents to children, 136 * (i.e. one can't tell which one is right). Mercurial walks from parents to children,
134 * and traces equal lines, wile HgBlameFacility walks from child to parents and records 137 * and traces equal lines, while HgBlameFacility walks from child to parents and records
135 * changes (additions). Seems it processes branch with rev3 and rev6 first 138 * changes (additions). Seems it processes branch with rev3 and rev6 first
136 * (printout in context.py, annotate and annotate.pair reveals that), and the line 0_5 139 * (printout in context.py, annotate and annotate.pair reveals that), and the line 0_5
137 * comes as unchanged through this branch, and later processing rev2 and rev4 doesn't 140 * comes as unchanged through this branch, and later processing rev2 and rev4 doesn't
138 * change that. 141 * change that.
139 */ 142 */
257 ai = new AnnotateInspector(); 260 ai = new AnnotateInspector();
258 cmd.execute(ai); 261 cmd.execute(ai);
259 ar.run(changeset, false); 262 ar.run(changeset, false);
260 doAnnotateLineCheck(changeset, ar.getLines(), ai.changesets, ai.lines); 263 doAnnotateLineCheck(changeset, ar.getLines(), ai.changesets, ai.lines);
261 } 264 }
265
266 // FIXME add originLineNumber to HgAnnotateCommand#LineInfo, pass it from FileAnnotate, test
262 267
263 private void doAnnotateLineCheck(int cs, String[] hgAnnotateLines, List<Integer> cmdChangesets, List<String> cmdLines) { 268 private void doAnnotateLineCheck(int cs, String[] hgAnnotateLines, List<Integer> cmdChangesets, List<String> cmdLines) {
264 assertTrue("[sanity]", hgAnnotateLines.length > 0); 269 assertTrue("[sanity]", hgAnnotateLines.length > 0);
265 assertEquals("Number of lines reported by native annotate and our impl", hgAnnotateLines.length, cmdLines.size()); 270 assertEquals("Number of lines reported by native annotate and our impl", hgAnnotateLines.length, cmdLines.size());
266 271
365 for (int cs : new int[] { 24, 46, 49, 52, 59, 62, 64, TIP}) { 370 for (int cs : new int[] { 24, 46, 49, 52, 59, 62, 64, TIP}) {
366 doLineAnnotateTest(df, cs, op); 371 doLineAnnotateTest(df, cs, op);
367 } 372 }
368 errorCollector.verify(); 373 errorCollector.verify();
369 */ 374 */
370 FileAnnotateInspector fa = new FileAnnotateInspector(); 375 ForwardAnnotateInspector insp = new ForwardAnnotateInspector();
371 diffCmd.range(0, 8).order(NewToOld); 376 diffCmd.range(0, 8).order(insp.iterateDirection());
372 diffCmd.executeAnnotate(new FileAnnotation(fa)); 377 diffCmd.executeAnnotate(insp);
373 for (int i = 0; i < fa.lineRevisions.length; i++) { 378 AnnotateInspector fa = new AnnotateInspector().fill(8, insp);
374 System.out.printf("%d: %s", fa.lineRevisions[i], fa.line(i) == null ? "null\n" : fa.line(i)); 379 for (int i = 0; i < fa.changesets.size(); i++) {
380 final String line = fa.lines.get(i);
381 System.out.printf("%d: %s", fa.changesets.get(i), line == null ? "null\n" : line);
375 } 382 }
376 } 383 }
377 384
378 public static void main(String[] args) throws Throwable { 385 public static void main(String[] args) throws Throwable {
379 TestBlame tt = new TestBlame(); 386 TestBlame tt = new TestBlame();
474 lineStart = ++lineEnd; 481 lineStart = ++lineEnd;
475 } while (lineStart < seq.length()); 482 } while (lineStart < seq.length());
476 } 483 }
477 } 484 }
478 485
479 private static class FileAnnotateInspector implements LineInspector {
480 private Integer[] lineRevisions;
481 private String[] lines;
482
483 FileAnnotateInspector() {
484 }
485
486 public void line(int lineNumber, int changesetRevIndex, HgBlameInspector.BlockData lineContent, LineDescriptor ld) {
487 if (lineRevisions == null) {
488 lineRevisions = new Integer[ld.totalLines()];
489 Arrays.fill(lineRevisions, NO_REVISION);
490 lines = new String[ld.totalLines()];
491 }
492 lineRevisions[lineNumber] = changesetRevIndex;
493 lines[lineNumber] = new String(lineContent.asArray());
494 }
495
496 public String line(int i) {
497 return lines[i];
498 }
499 }
500
501 @SuppressWarnings("unused") 486 @SuppressWarnings("unused")
502 private static class LineDumpInspector implements HgBlameInspector { 487 private static class LineDumpInspector implements HgBlameInspector {
503 488
504 private final boolean lineByLine; 489 private final boolean lineByLine;
505 490
542 527
543 static class AnnotateInspector implements HgAnnotateCommand.Inspector { 528 static class AnnotateInspector implements HgAnnotateCommand.Inspector {
544 private int lineNumber = 1; 529 private int lineNumber = 1;
545 public final ArrayList<String> lines = new ArrayList<String>(); 530 public final ArrayList<String> lines = new ArrayList<String>();
546 public final ArrayList<Integer> changesets = new ArrayList<Integer>(); 531 public final ArrayList<Integer> changesets = new ArrayList<Integer>();
547 532
533 AnnotateInspector fill(int rev, ReverseAnnotateInspector ai) throws HgCallbackTargetException, CancelledException {
534 ai.report(rev, this, ProgressSupport.Factory.get(null), CancelSupport.Factory.get(null));
535 return this;
536 }
537 AnnotateInspector fill(int rev, ForwardAnnotateInspector ai) throws HgCallbackTargetException, CancelledException {
538 ai.report(rev, this, ProgressSupport.Factory.get(null), CancelSupport.Factory.get(null));
539 return this;
540 }
541
548 public void next(LineInfo lineInfo) throws HgCallbackTargetException { 542 public void next(LineInfo lineInfo) throws HgCallbackTargetException {
549 Assert.assertEquals(lineInfo.getLineNumber(), lineNumber); 543 Assert.assertEquals(lineInfo.getLineNumber(), lineNumber);
550 lineNumber++; 544 lineNumber++;
551 lines.add(new String(lineInfo.getContent())); 545 lines.add(new String(lineInfo.getContent()));
552 changesets.add(lineInfo.getChangesetIndex()); 546 changesets.add(lineInfo.getChangesetIndex());