1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45 package org.eclipse.jgit.revplot;
46
47 import static org.eclipse.jgit.lib.Constants.R_HEADS;
48 import static org.eclipse.jgit.lib.Constants.R_REMOTES;
49 import static org.eclipse.jgit.lib.Constants.R_TAGS;
50
51 import java.io.IOException;
52 import java.util.Arrays;
53 import java.util.Collection;
54 import java.util.Collections;
55 import java.util.Comparator;
56 import java.util.HashMap;
57 import java.util.HashSet;
58 import java.util.Map;
59 import java.util.Set;
60
61 import org.eclipse.jgit.errors.IncorrectObjectTypeException;
62 import org.eclipse.jgit.errors.MissingObjectException;
63 import org.eclipse.jgit.internal.JGitText;
64 import org.eclipse.jgit.lib.AnyObjectId;
65 import org.eclipse.jgit.lib.PersonIdent;
66 import org.eclipse.jgit.lib.Ref;
67 import org.eclipse.jgit.lib.Repository;
68 import org.eclipse.jgit.revwalk.RevCommit;
69 import org.eclipse.jgit.revwalk.RevObject;
70 import org.eclipse.jgit.revwalk.RevSort;
71 import org.eclipse.jgit.revwalk.RevTag;
72 import org.eclipse.jgit.revwalk.RevWalk;
73
74
75
76
77 public class PlotWalk extends RevWalk {
78
79 private Map<AnyObjectId, Set<Ref>> additionalRefMap;
80
81 private Map<AnyObjectId, Set<Ref>> reverseRefMap;
82
83 private Repository repository;
84
85
86 @Override
87 public void dispose() {
88 super.dispose();
89 if (reverseRefMap != null) {
90 reverseRefMap.clear();
91 reverseRefMap = null;
92 }
93 if (additionalRefMap != null) {
94 additionalRefMap.clear();
95 additionalRefMap = null;
96 }
97 repository = null;
98 }
99
100
101
102
103
104
105
106 public PlotWalk(Repository repo) {
107 super(repo);
108 super.sort(RevSort.TOPO, true);
109 additionalRefMap = new HashMap<>();
110 repository = repo;
111 }
112
113
114
115
116
117
118
119
120 public void addAdditionalRefs(Iterable<Ref> refs) throws IOException {
121 for (Ref ref : refs) {
122 Set<Ref> set = additionalRefMap.get(ref.getObjectId());
123 if (set == null)
124 set = Collections.singleton(ref);
125 else {
126 set = new HashSet<>(set);
127 set.add(ref);
128 }
129 additionalRefMap.put(ref.getObjectId(), set);
130 }
131 }
132
133
134 @Override
135 public void sort(RevSort s, boolean use) {
136 if (s == RevSort.TOPO && !use)
137 throw new IllegalArgumentException(JGitText.get().topologicalSortRequired);
138 super.sort(s, use);
139 }
140
141
142 @Override
143 protected RevCommit createCommit(AnyObjectId id) {
144 return new PlotCommit(id);
145 }
146
147
148 @Override
149 public RevCommit next() throws MissingObjectException,
150 IncorrectObjectTypeException, IOException {
151 PlotCommit<?> pc = (PlotCommit) super.next();
152 if (pc != null)
153 pc.refs = getRefs(pc);
154 return pc;
155 }
156
157 private Ref[] getRefs(AnyObjectId commitId) {
158 if (reverseRefMap == null) {
159 reverseRefMap = repository.getAllRefsByPeeledObjectId();
160 for (Map.Entry<AnyObjectId, Set<Ref>> entry : additionalRefMap
161 .entrySet()) {
162 Set<Ref> set = reverseRefMap.get(entry.getKey());
163 Set<Ref> additional = entry.getValue();
164 if (set != null) {
165 if (additional.size() == 1) {
166
167 additional = new HashSet<>(additional);
168 }
169 additional.addAll(set);
170 }
171 reverseRefMap.put(entry.getKey(), additional);
172 }
173 additionalRefMap.clear();
174 additionalRefMap = null;
175 }
176 Collection<Ref> list = reverseRefMap.get(commitId);
177 if (list == null) {
178 return PlotCommit.NO_REFS;
179 } else {
180 Ref[] tags = list.toArray(new Ref[0]);
181 Arrays.sort(tags, new PlotRefComparator());
182 return tags;
183 }
184 }
185
186 class PlotRefComparator implements Comparator<Ref> {
187 @Override
188 public int compare(Reff" href="../../../../org/eclipse/jgit/lib/Ref.html#Ref">Ref o1, Ref o2) {
189 try {
190 RevObject obj1 = parseAny(o1.getObjectId());
191 RevObject obj2 = parseAny(o2.getObjectId());
192 long t1 = timeof(obj1);
193 long t2 = timeof(obj2);
194 if (t1 > t2)
195 return -1;
196 if (t1 < t2)
197 return 1;
198 } catch (IOException e) {
199
200 }
201
202 int cmp = kind(o1) - kind(o2);
203 if (cmp == 0)
204 cmp = o1.getName().compareTo(o2.getName());
205 return cmp;
206 }
207
208 long timeof(RevObject o) {
209 if (o instanceof RevCommit)
210 return ((RevCommit) o).getCommitTime();
211 if (o instanceof RevTag) {
212 RevTag tag = (RevTag) o;
213 try {
214 parseBody(tag);
215 } catch (IOException e) {
216 return 0;
217 }
218 PersonIdent who = tag.getTaggerIdent();
219 return who != null ? who.getWhen().getTime() : 0;
220 }
221 return 0;
222 }
223
224 int kind(Ref r) {
225 if (r.getName().startsWith(R_TAGS))
226 return 0;
227 if (r.getName().startsWith(R_HEADS))
228 return 1;
229 if (r.getName().startsWith(R_REMOTES))
230 return 2;
231 return 3;
232 }
233 }
234 }