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