Mercurial > hg4j
comparison src/com/tmate/hgkit/ll/Revlog.java @ 29:6cce719bbb62
Collector for nodes and their parents
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Tue, 11 Jan 2011 04:37:29 +0100 |
parents | d4fdd1845b3f |
children | 346b66add79d |
comparison
equal
deleted
inserted
replaced
28:b2251b7a9823 | 29:6cce719bbb62 |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2010, 2011 Artem Tikhomirov | 2 * Copyright (c) 2010, 2011 Artem Tikhomirov |
3 */ | 3 */ |
4 package com.tmate.hgkit.ll; | 4 package com.tmate.hgkit.ll; |
5 | |
6 import java.util.Collection; | |
7 import java.util.Collections; | |
8 import java.util.HashMap; | |
9 import java.util.LinkedHashSet; | |
10 import java.util.Map; | |
11 import java.util.Set; | |
5 | 12 |
6 /** | 13 /** |
7 * | 14 * |
8 * @author artem | 15 * @author artem |
9 */ | 16 */ |
25 } | 32 } |
26 | 33 |
27 public int getRevisionCount() { | 34 public int getRevisionCount() { |
28 return content.revisionCount(); | 35 return content.revisionCount(); |
29 } | 36 } |
30 | 37 |
31 // FIXME byte[] data might be too expensive, for few usecases it may be better to have intermediate Access object (when we don't need full data | 38 // FIXME byte[] data might be too expensive, for few usecases it may be better to have intermediate Access object (when we don't need full data |
32 // instantly - e.g. calculate hash, or comparing two revisions | 39 // instantly - e.g. calculate hash, or comparing two revisions |
40 // XXX seems that RevlogStream is better place for this class. | |
33 public interface Inspector { | 41 public interface Inspector { |
34 // XXX boolean retVal to indicate whether to continue? | 42 // XXX boolean retVal to indicate whether to continue? |
35 // TODO specify nodeid and data length, and reuse policy (i.e. if revlog stream doesn't reuse nodeid[] for each call) | 43 // TODO specify nodeid and data length, and reuse policy (i.e. if revlog stream doesn't reuse nodeid[] for each call) |
36 void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[/*20*/] nodeid, byte[] data); | 44 void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[/*20*/] nodeid, byte[] data); |
37 } | 45 } |
46 | |
47 /* | |
48 * XXX think over if it's better to do either: | |
49 * pw = getChangelog().new ParentWalker(); pw.init() and pass pw instance around as needed | |
50 * or | |
51 * add Revlog#getParentWalker(), static class, make cons() and #init package-local, and keep SoftReference to allow walker reuse. | |
52 * | |
53 * and yes, walker is not a proper name | |
54 */ | |
55 public final class ParentWalker { | |
56 private Map<Nodeid, Nodeid> firstParent; | |
57 private Map<Nodeid, Nodeid> secondParent; | |
58 private Set<Nodeid> allNodes; | |
59 | |
60 public ParentWalker() { | |
61 firstParent = secondParent = Collections.emptyMap(); | |
62 allNodes = Collections.emptySet(); | |
63 } | |
64 | |
65 public void init() { | |
66 final RevlogStream stream = Revlog.this.content; | |
67 final int revisionCount = stream.revisionCount(); | |
68 firstParent = new HashMap<Nodeid, Nodeid>(revisionCount); | |
69 secondParent = new HashMap<Nodeid, Nodeid>(firstParent.size() >> 1); // assume branches/merges are less frequent | |
70 allNodes = new LinkedHashSet<Nodeid>(); | |
71 | |
72 Inspector insp = new Inspector() { | |
73 final Nodeid[] sequentialRevisionNodeids = new Nodeid[revisionCount]; | |
74 int ix = 0; | |
75 public void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[] nodeid, byte[] data) { | |
76 if (ix != revisionNumber) { | |
77 // XXX temp code, just to make sure I understand what's going on here | |
78 throw new IllegalStateException(); | |
79 } | |
80 if (parent1Revision >= revisionNumber || parent2Revision >= revisionNumber) { | |
81 throw new IllegalStateException(); // sanity, revisions are sequential | |
82 } | |
83 final Nodeid nid = new Nodeid(nodeid, true); | |
84 sequentialRevisionNodeids[ix++] = nid; | |
85 allNodes.add(nid); | |
86 if (parent1Revision != -1) { | |
87 firstParent.put(nid, sequentialRevisionNodeids[parent1Revision]); | |
88 if (parent2Revision != -1) { | |
89 secondParent.put(nid, sequentialRevisionNodeids[parent2Revision]); | |
90 } | |
91 } | |
92 } | |
93 }; | |
94 stream.iterate(0, -1, false, insp); | |
95 } | |
96 | |
97 public Set<Nodeid> allNodes() { | |
98 return Collections.unmodifiableSet(allNodes); | |
99 } | |
100 | |
101 // null if none | |
102 public Nodeid firstParent(Nodeid nid) { | |
103 return firstParent.get(nid); | |
104 } | |
105 | |
106 public Nodeid secondParent(Nodeid nid) { | |
107 return secondParent.get(nid); | |
108 } | |
109 | |
110 public boolean appendParentsOf(Nodeid nid, Collection<Nodeid> c) { | |
111 Nodeid p1 = firstParent(nid); | |
112 boolean modified = false; | |
113 if (p1 != null) { | |
114 modified = c.add(p1); | |
115 Nodeid p2 = secondParent(nid); | |
116 if (p2 != null) { | |
117 modified = c.add(p2) || modified; | |
118 } | |
119 } | |
120 return modified; | |
121 } | |
122 } | |
38 } | 123 } |