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<Ref>(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 public int compare(Ref o1, Ref o2) {
151 try {
152 RevObject obj1 = parseAny(o1.getObjectId());
153 RevObject obj2 = parseAny(o2.getObjectId());
154 long t1 = timeof(obj1);
155 long t2 = timeof(obj2);
156 if (t1 > t2)
157 return -1;
158 if (t1 < t2)
159 return 1;
160 } catch (IOException e) {
161
162 }
163
164 int cmp = kind(o1) - kind(o2);
165 if (cmp == 0)
166 cmp = o1.getName().compareTo(o2.getName());
167 return cmp;
168 }
169
170 long timeof(RevObject o) {
171 if (o instanceof RevCommit)
172 return ((RevCommit) o).getCommitTime();
173 if (o instanceof RevTag) {
174 RevTag tag = (RevTag) o;
175 try {
176 parseBody(tag);
177 } catch (IOException e) {
178 return 0;
179 }
180 PersonIdent who = tag.getTaggerIdent();
181 return who != null ? who.getWhen().getTime() : 0;
182 }
183 return 0;
184 }
185
186 int kind(Ref r) {
187 if (r.getName().startsWith(R_TAGS))
188 return 0;
189 if (r.getName().startsWith(R_HEADS))
190 return 1;
191 if (r.getName().startsWith(R_REMOTES))
192 return 2;
193 return 3;
194 }
195 }
196 }