comparison src/org/tmatesoft/hg/internal/BlameHelper.java @ 625:b4948b159ab1

Refactor internals of blame support, tests
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Tue, 21 May 2013 17:24:22 +0200
parents 707b5c7c6fa4
children 6526d8adbc0f
comparison
equal deleted inserted replaced
624:507602cb4fb3 625:b4948b159ab1
14 * the terms of a license other than GNU General Public License 14 * the terms of a license other than GNU General Public License
15 * contact TMate Software at support@hg4j.com 15 * contact TMate Software at support@hg4j.com
16 */ 16 */
17 package org.tmatesoft.hg.internal; 17 package org.tmatesoft.hg.internal;
18 18
19 import static org.tmatesoft.hg.core.HgIterateDirection.OldToNew;
19 import static org.tmatesoft.hg.repo.HgRepository.NO_REVISION; 20 import static org.tmatesoft.hg.repo.HgRepository.NO_REVISION;
20 21
21 import java.util.LinkedList; 22 import java.util.LinkedList;
22 import java.util.ListIterator; 23 import java.util.ListIterator;
23 24
46 public class BlameHelper { 47 public class BlameHelper {
47 48
48 private final HgBlameInspector insp; 49 private final HgBlameInspector insp;
49 private FileLinesCache linesCache; 50 private FileLinesCache linesCache;
50 51
51 // FIXME exposing internals (use of FileLinesCache through cons arg and #useFileUpTo) smells bad, refactor! 52 public BlameHelper(HgBlameInspector inspector) {
52
53 public BlameHelper(HgBlameInspector inspector, int cacheHint) {
54 insp = inspector; 53 insp = inspector;
54 }
55
56 /**
57 * Build history of the file for the specified range (follow renames if necessary). This history
58 * is used to access various file revision data during subsequent {@link #diff(int, int, int, int)} and
59 * {@link #annotateChange(int, int, int[], int[])} calls. Callers can use returned history for own approaches
60 * to iteration over file history.
61
62 * <p>NOTE, clogRevIndexEnd has to list name of the supplied file in the corresponding manifest,
63 * as it's not possible to trace rename history otherwise.
64 */
65 public FileHistory prepare(HgDataFile df, int clogRevIndexStart, int clogRevIndexEnd) {
66 assert clogRevIndexStart <= clogRevIndexEnd;
67 FileHistory fileHistory = new FileHistory(df, clogRevIndexStart, clogRevIndexEnd);
68 fileHistory.build();
69 int cacheHint = 5; // cache comes useful when we follow merge branches and don't want to
70 // parse base revision twice. There's no easy way to determine max(distance(all(base,merge))),
71 // hence the heuristics to use the longest history chunk:
72 for (FileRevisionHistoryChunk c : fileHistory.iterate(OldToNew)) {
73 // iteration order is not important here
74 if (c.revisionCount() > cacheHint) {
75 cacheHint = c.revisionCount();
76 }
77 }
55 linesCache = new FileLinesCache(cacheHint); 78 linesCache = new FileLinesCache(cacheHint);
56 } 79 for (FileRevisionHistoryChunk fhc : fileHistory.iterate(OldToNew)) {
57 80 // iteration order is not important here
58 public void useFileUpTo(HgDataFile df, int clogRevIndex) { 81 linesCache.useFileUpTo(fhc.getFile(), fhc.getEndChangeset());
59 linesCache.useFileUpTo(df, clogRevIndex); 82 }
83 return fileHistory;
60 } 84 }
61 85
62 // NO_REVISION is not allowed as any argument 86 // NO_REVISION is not allowed as any argument
63 public void diff(int fileRevIndex1, int clogRevIndex1, int fileRevIndex2, int clogRevIndex2) throws HgCallbackTargetException { 87 public void diff(int fileRevIndex1, int clogRevIndex1, int fileRevIndex2, int clogRevIndex2) throws HgCallbackTargetException {
64 HgDataFile targetFile = linesCache.getFile(clogRevIndex2); 88 HgDataFile targetFile = linesCache.getFile(clogRevIndex2);
114 private static class FileLinesCache { 138 private static class FileLinesCache {
115 private final LinkedList<Pair<Integer, LineSequence>> lruCache; 139 private final LinkedList<Pair<Integer, LineSequence>> lruCache;
116 private final int limit; 140 private final int limit;
117 private final LinkedList<Pair<Integer, HgDataFile>> files; // TODO in fact, need sparse array 141 private final LinkedList<Pair<Integer, HgDataFile>> files; // TODO in fact, need sparse array
118 142
143 /**
144 * @param lruLimit how many parsed file revisions to keep
145 */
119 public FileLinesCache(int lruLimit) { 146 public FileLinesCache(int lruLimit) {
120 limit = lruLimit; 147 limit = lruLimit;
121 lruCache = new LinkedList<Pair<Integer, LineSequence>>(); 148 lruCache = new LinkedList<Pair<Integer, LineSequence>>();
122 files = new LinkedList<Pair<Integer,HgDataFile>>(); 149 files = new LinkedList<Pair<Integer,HgDataFile>>();
123 } 150 }