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 package org.eclipse.jgit.internal.storage.pack;
45
46 import java.io.IOException;
47 import java.util.Arrays;
48
49 import org.eclipse.jgit.errors.IncorrectObjectTypeException;
50 import org.eclipse.jgit.errors.MissingObjectException;
51 import org.eclipse.jgit.lib.BitmapIndex;
52 import org.eclipse.jgit.lib.BitmapIndex.Bitmap;
53 import org.eclipse.jgit.lib.BitmapIndex.BitmapBuilder;
54 import org.eclipse.jgit.lib.Constants;
55 import org.eclipse.jgit.lib.NullProgressMonitor;
56 import org.eclipse.jgit.lib.ObjectId;
57 import org.eclipse.jgit.lib.ProgressMonitor;
58 import org.eclipse.jgit.revwalk.ObjectWalk;
59 import org.eclipse.jgit.revwalk.RevCommit;
60 import org.eclipse.jgit.revwalk.RevFlag;
61 import org.eclipse.jgit.revwalk.RevObject;
62 import org.eclipse.jgit.revwalk.RevWalk;
63 import org.eclipse.jgit.revwalk.filter.RevFilter;
64
65
66 final class PackWriterBitmapWalker {
67
68 private final ObjectWalk walker;
69
70 private final BitmapIndex bitmapIndex;
71
72 private final ProgressMonitor pm;
73
74 private long countOfBitmapIndexMisses;
75
76 PackWriterBitmapWalker(
77 ObjectWalk walker, BitmapIndex bitmapIndex, ProgressMonitor pm) {
78 this.walker = walker;
79 this.bitmapIndex = bitmapIndex;
80 this.pm = (pm == null) ? NullProgressMonitor.INSTANCE : pm;
81 }
82
83 long getCountOfBitmapIndexMisses() {
84 return countOfBitmapIndexMisses;
85 }
86
87 BitmapBuilder findObjects(Iterable<? extends ObjectId> start, BitmapBuilder seen,
88 boolean ignoreMissing)
89 throws MissingObjectException, IncorrectObjectTypeException,
90 IOException {
91 if (!ignoreMissing) {
92 return findObjectsWalk(start, seen, false);
93 }
94
95 try {
96 return findObjectsWalk(start, seen, true);
97 } catch (MissingObjectException ignore) {
98
99
100 }
101
102 final BitmapBuilder result = bitmapIndex.newBitmapBuilder();
103 for (ObjectId obj : start) {
104 Bitmap bitmap = bitmapIndex.getBitmap(obj);
105 if (bitmap != null) {
106 result.or(bitmap);
107 }
108 }
109
110 for (ObjectId obj : start) {
111 if (result.contains(obj)) {
112 continue;
113 }
114 try {
115 result.or(findObjectsWalk(Arrays.asList(obj), result, false));
116 } catch (MissingObjectException ignore) {
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131 }
132 }
133 return result;
134 }
135
136 private BitmapBuilder findObjectsWalk(Iterable<? extends ObjectId> start, BitmapBuilder seen,
137 boolean ignoreMissingStart)
138 throws MissingObjectException, IncorrectObjectTypeException,
139 IOException {
140 walker.reset();
141 final BitmapBuilder bitmapResult = bitmapIndex.newBitmapBuilder();
142
143 for (ObjectId obj : start) {
144 Bitmap bitmap = bitmapIndex.getBitmap(obj);
145 if (bitmap != null)
146 bitmapResult.or(bitmap);
147 }
148
149 boolean marked = false;
150 for (ObjectId obj : start) {
151 try {
152 if (!bitmapResult.contains(obj)) {
153 walker.markStart(walker.parseAny(obj));
154 marked = true;
155 }
156 } catch (MissingObjectException e) {
157 if (ignoreMissingStart)
158 continue;
159 throw e;
160 }
161 }
162
163 if (marked) {
164 if (seen == null) {
165 walker.setRevFilter(new AddToBitmapFilter(bitmapResult));
166 } else {
167 walker.setRevFilter(
168 new AddUnseenToBitmapFilter(seen, bitmapResult));
169 }
170
171 while (walker.next() != null) {
172
173
174
175
176
177
178
179
180
181 pm.update(1);
182 countOfBitmapIndexMisses++;
183 }
184
185 RevObject ro;
186 while ((ro = walker.nextObject()) != null) {
187 bitmapResult.addObject(ro, ro.getType());
188 pm.update(1);
189 }
190 }
191
192 return bitmapResult;
193 }
194
195
196
197
198
199
200
201
202
203
204
205 static class AddToBitmapFilter extends RevFilter {
206 private final BitmapBuilder bitmap;
207
208 AddToBitmapFilter(BitmapBuilder bitmap) {
209 this.bitmap = bitmap;
210 }
211
212 @Override
213 public final boolean include(RevWalk walker, RevCommit cmit) {
214 Bitmap visitedBitmap;
215
216 if (bitmap.contains(cmit)) {
217
218 } else if ((visitedBitmap = bitmap.getBitmapIndex()
219 .getBitmap(cmit)) != null) {
220 bitmap.or(visitedBitmap);
221 } else {
222 bitmap.addObject(cmit, Constants.OBJ_COMMIT);
223 return true;
224 }
225
226 for (RevCommit p : cmit.getParents()) {
227 p.add(RevFlag.SEEN);
228 }
229 return false;
230 }
231
232 @Override
233 public final RevFilter clone() {
234 throw new UnsupportedOperationException();
235 }
236
237 @Override
238 public final boolean requiresCommitBody() {
239 return false;
240 }
241 }
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257 static class AddUnseenToBitmapFilter extends RevFilter {
258 private final BitmapBuilder seen;
259 private final BitmapBuilder bitmap;
260
261 AddUnseenToBitmapFilter(BitmapBuilder seen, BitmapBuilder bitmapResult) {
262 this.seen = seen;
263 this.bitmap = bitmapResult;
264 }
265
266 @Override
267 public final boolean include(RevWalk walker, RevCommit cmit) {
268 Bitmap visitedBitmap;
269
270 if (seen.contains(cmit) || bitmap.contains(cmit)) {
271
272 } else if ((visitedBitmap = bitmap.getBitmapIndex()
273 .getBitmap(cmit)) != null) {
274 bitmap.or(visitedBitmap);
275 } else {
276 bitmap.addObject(cmit, Constants.OBJ_COMMIT);
277 return true;
278 }
279
280 for (RevCommit p : cmit.getParents()) {
281 p.add(RevFlag.SEEN);
282 }
283 return false;
284 }
285
286 @Override
287 public final RevFilter clone() {
288 throw new UnsupportedOperationException();
289 }
290
291 @Override
292 public final boolean requiresCommitBody() {
293 return false;
294 }
295 }
296 }