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