comparison src/org/tmatesoft/hg/repo/HgDataFile.java @ 305:ae8d116f4ee2

Experimental code to build file history
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Thu, 22 Sep 2011 03:57:38 +0200
parents 650b45d290b1
children 971baa95fb07
comparison
equal deleted inserted replaced
304:85b8efde5586 305:ae8d116f4ee2
26 import java.nio.ByteBuffer; 26 import java.nio.ByteBuffer;
27 import java.nio.channels.FileChannel; 27 import java.nio.channels.FileChannel;
28 import java.util.ArrayList; 28 import java.util.ArrayList;
29 import java.util.Arrays; 29 import java.util.Arrays;
30 import java.util.Collection; 30 import java.util.Collection;
31 import java.util.Collections;
32 import java.util.List;
33 import java.util.NoSuchElementException;
31 34
32 import org.tmatesoft.hg.core.HgDataStreamException; 35 import org.tmatesoft.hg.core.HgDataStreamException;
33 import org.tmatesoft.hg.core.HgException; 36 import org.tmatesoft.hg.core.HgException;
34 import org.tmatesoft.hg.core.Nodeid; 37 import org.tmatesoft.hg.core.Nodeid;
35 import org.tmatesoft.hg.internal.DataAccess; 38 import org.tmatesoft.hg.internal.DataAccess;
39 import org.tmatesoft.hg.internal.Experimental;
36 import org.tmatesoft.hg.internal.FilterByteChannel; 40 import org.tmatesoft.hg.internal.FilterByteChannel;
37 import org.tmatesoft.hg.internal.FilterDataAccess; 41 import org.tmatesoft.hg.internal.FilterDataAccess;
38 import org.tmatesoft.hg.internal.IntMap; 42 import org.tmatesoft.hg.internal.IntMap;
39 import org.tmatesoft.hg.internal.RevlogStream; 43 import org.tmatesoft.hg.internal.RevlogStream;
44 import org.tmatesoft.hg.repo.HgChangelog.RawChangeset;
40 import org.tmatesoft.hg.util.ByteChannel; 45 import org.tmatesoft.hg.util.ByteChannel;
41 import org.tmatesoft.hg.util.CancelSupport; 46 import org.tmatesoft.hg.util.CancelSupport;
42 import org.tmatesoft.hg.util.CancelledException; 47 import org.tmatesoft.hg.util.CancelledException;
48 import org.tmatesoft.hg.util.Pair;
43 import org.tmatesoft.hg.util.Path; 49 import org.tmatesoft.hg.util.Path;
44 import org.tmatesoft.hg.util.ProgressSupport; 50 import org.tmatesoft.hg.util.ProgressSupport;
45 51
46 52
47 53
221 throw new HgDataStreamException(getPath(), ex); 227 throw new HgDataStreamException(getPath(), ex);
222 } catch (HgException ex) { 228 } catch (HgException ex) {
223 // shall not happen, unless we changed ContentPipe or its subclass 229 // shall not happen, unless we changed ContentPipe or its subclass
224 throw new HgDataStreamException(getPath(), ex.getClass().getName(), ex); 230 throw new HgDataStreamException(getPath(), ex.getClass().getName(), ex);
225 } 231 }
232 }
233
234 @Experimental(reason="Investigate approaches to build complete file history log")
235 public interface HistoryWalker {
236 void next();
237 boolean hasNext();
238 Nodeid changesetRevision();
239 RawChangeset changeset();
240 boolean isFork();
241 boolean isJoin();
242 Pair<Nodeid, Nodeid> parentChangesets();
243 Collection<Nodeid> childChangesets();
244 }
245
246 public HistoryWalker history() {
247 final boolean[] needsSorting = { false };
248 class HistoryNode {
249 int changeset;
250 Nodeid cset;
251 HistoryNode parent1, parent2;
252 List<HistoryNode> children;
253
254 public HistoryNode(int cs, HistoryNode p1, HistoryNode p2) {
255 changeset = cs;
256 parent1 = p1;
257 parent2 = p2;
258 if (p1 != null) {
259 p1.addChild(this);
260 }
261 if (p2 != null) {
262 p2.addChild(this);
263 }
264 }
265
266 public Nodeid changesetRevision() {
267 if (cset == null) {
268 cset = getRepo().getChangelog().getRevision(changeset);
269 }
270 return cset;
271 }
272
273 public void addChild(HistoryNode child) {
274 if (children == null) {
275 children = new ArrayList<HistoryNode>(2);
276 }
277 children.add(child);
278 }
279 }
280 final HistoryNode[] completeHistory = new HistoryNode[getRevisionCount()];
281 final int[] commitRevisions = new int[completeHistory.length];
282 RevlogStream.Inspector insp = new RevlogStream.Inspector() {
283 public void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[] nodeid, DataAccess data) {
284 if (revisionNumber > 0) {
285 if (commitRevisions[revisionNumber-1] > linkRevision) {
286 needsSorting[0] = true;
287 }
288 }
289 HistoryNode p1 = null, p2 = null;
290 if (parent1Revision != -1) {
291 p1 = completeHistory[parent1Revision];
292 }
293 if (parent2Revision != -1) {
294 p2 = completeHistory[parent2Revision];
295 }
296 completeHistory[revisionNumber] = new HistoryNode(linkRevision, p1, p2);
297 }
298 };
299 content.iterate(0, getLastRevision(), false, insp);
300 // XXX may read changeset revisions at once (to avoid numerous changelog.getRevision reads)
301 // but perhaps just nodeids, not RawChangeset (changelog.iterate(data=false)
302 // XXX sort completeHistory according to changeset numbers?
303 return new HistoryWalker() {
304 private int index = -1;
305
306 public void next() {
307 if (!hasNext()) {
308 throw new NoSuchElementException();
309 }
310 index++;
311 }
312
313 public boolean hasNext() {
314 return index+1 < completeHistory.length;
315 }
316
317 public Pair<Nodeid, Nodeid> parentChangesets() {
318 HistoryNode p;
319 Nodeid p1, p2;
320 if ((p = completeHistory[index].parent1) != null) {
321 p1 = p.changesetRevision();
322 } else {
323 p1 = Nodeid.NULL;
324 }
325 if ((p = completeHistory[index].parent2) != null) {
326 p2 = p.changesetRevision();
327 } else {
328 p2 = Nodeid.NULL;
329 }
330 return new Pair<Nodeid, Nodeid>(p1, p2);
331 }
332
333 public boolean isJoin() {
334 return completeHistory[index].parent1 != null && completeHistory[index].parent2 != null;
335 }
336
337 public boolean isFork() {
338 HistoryNode n = completeHistory[index];
339 return n.children != null && n.children.size() > 1;
340 }
341
342 public Collection<Nodeid> childChangesets() {
343 HistoryNode n = completeHistory[index];
344 if (n.children == null) {
345 return Collections.emptyList();
346 }
347 ArrayList<Nodeid> rv = new ArrayList<Nodeid>(n.children.size());
348 for (HistoryNode hn : n.children) {
349 rv.add(hn.changesetRevision());
350 }
351 return rv;
352 }
353
354 public Nodeid changesetRevision() {
355 return completeHistory[index].changesetRevision();
356 }
357
358 public RawChangeset changeset() {
359
360 return null;
361 }
362 };
226 } 363 }
227 364
228 public void history(HgChangelog.Inspector inspector) { 365 public void history(HgChangelog.Inspector inspector) {
229 history(0, getLastRevision(), inspector); 366 history(0, getLastRevision(), inspector);
230 } 367 }