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.HashSet;
57 import java.util.Map;
58 import java.util.Set;
59
60 import org.eclipse.jgit.errors.IncorrectObjectTypeException;
61 import org.eclipse.jgit.errors.MissingObjectException;
62 import org.eclipse.jgit.internal.JGitText;
63 import org.eclipse.jgit.lib.AnyObjectId;
64 import org.eclipse.jgit.lib.PersonIdent;
65 import org.eclipse.jgit.lib.Ref;
66 import org.eclipse.jgit.lib.Repository;
67 import org.eclipse.jgit.revwalk.RevCommit;
68 import org.eclipse.jgit.revwalk.RevObject;
69 import org.eclipse.jgit.revwalk.RevSort;
70 import org.eclipse.jgit.revwalk.RevTag;
71 import org.eclipse.jgit.revwalk.RevWalk;
72
73
74
75
76 public class PlotWalk extends RevWalk {
77
78 private Map<AnyObjectId, Set<Ref>> reverseRefMap;
79
80
81 @Override
82 public void dispose() {
83 super.dispose();
84 reverseRefMap.clear();
85 }
86
87
88
89
90
91
92
93 public PlotWalk(Repository repo) {
94 super(repo);
95 super.sort(RevSort.TOPO, true);
96 reverseRefMap = repo.getAllRefsByPeeledObjectId();
97 }
98
99
100
101
102
103
104
105
106 public void addAdditionalRefs(Iterable<Ref> refs) throws IOException {
107 for (Ref ref : refs) {
108 Set<Ref> set = reverseRefMap.get(ref.getObjectId());
109 if (set == null)
110 set = Collections.singleton(ref);
111 else {
112 set = new HashSet<>(set);
113 set.add(ref);
114 }
115 reverseRefMap.put(ref.getObjectId(), set);
116 }
117 }
118
119
120 @Override
121 public void sort(RevSort s, boolean use) {
122 if (s == RevSort.TOPO && !use)
123 throw new IllegalArgumentException(JGitText.get().topologicalSortRequired);
124 super.sort(s, use);
125 }
126
127
128 @Override
129 protected RevCommit createCommit(AnyObjectId id) {
130 return new PlotCommit(id);
131 }
132
133
134 @Override
135 public RevCommit next() throws MissingObjectException,
136 IncorrectObjectTypeException, IOException {
137 PlotCommit<?> pc = (PlotCommit) super.next();
138 if (pc != null)
139 pc.refs = getRefs(pc);
140 return pc;
141 }
142
143 private Ref[] getRefs(AnyObjectId commitId) {
144 Collection<Ref> list = reverseRefMap.get(commitId);
145 if (list == null)
146 return PlotCommit.NO_REFS;
147 else {
148 Ref[] tags = list.toArray(new Ref[list.size()]);
149 Arrays.sort(tags, new PlotRefComparator());
150 return tags;
151 }
152 }
153
154 class PlotRefComparator implements Comparator<Ref> {
155 @Override
156 public int compare(Ref o1, Ref o2) {
157 try {
158 RevObject obj1 = parseAny(o1.getObjectId());
159 RevObject obj2 = parseAny(o2.getObjectId());
160 long t1 = timeof(obj1);
161 long t2 = timeof(obj2);
162 if (t1 > t2)
163 return -1;
164 if (t1 < t2)
165 return 1;
166 } catch (IOException e) {
167
168 }
169
170 int cmp = kind(o1) - kind(o2);
171 if (cmp == 0)
172 cmp = o1.getName().compareTo(o2.getName());
173 return cmp;
174 }
175
176 long timeof(RevObject o) {
177 if (o instanceof RevCommit)
178 return ((RevCommit) o).getCommitTime();
179 if (o instanceof RevTag) {
180 RevTag tag = (RevTag) o;
181 try {
182 parseBody(tag);
183 } catch (IOException e) {
184 return 0;
185 }
186 PersonIdent who = tag.getTaggerIdent();
187 return who != null ? who.getWhen().getTime() : 0;
188 }
189 return 0;
190 }
191
192 int kind(Ref r) {
193 if (r.getName().startsWith(R_TAGS))
194 return 0;
195 if (r.getName().startsWith(R_HEADS))
196 return 1;
197 if (r.getName().startsWith(R_REMOTES))
198 return 2;
199 return 3;
200 }
201 }
202 }