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.Set;
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.Constants;
53 import org.eclipse.jgit.lib.NullProgressMonitor;
54 import org.eclipse.jgit.lib.ObjectId;
55 import org.eclipse.jgit.lib.BitmapIndex.Bitmap;
56 import org.eclipse.jgit.lib.BitmapIndex.BitmapBuilder;
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(Set<? extends ObjectId> start, BitmapBuilder seen, boolean ignoreMissingStart)
88 throws MissingObjectException, IncorrectObjectTypeException,
89 IOException {
90 final BitmapBuilder bitmapResult = bitmapIndex.newBitmapBuilder();
91
92 for (ObjectId obj : start) {
93 Bitmap bitmap = bitmapIndex.getBitmap(obj);
94 if (bitmap != null)
95 bitmapResult.or(bitmap);
96 }
97
98 boolean marked = false;
99 for (ObjectId obj : start) {
100 try {
101 if (!bitmapResult.contains(obj)) {
102 walker.markStart(walker.parseAny(obj));
103 marked = true;
104 }
105 } catch (MissingObjectException e) {
106 if (ignoreMissingStart)
107 continue;
108 throw e;
109 }
110 }
111
112 if (marked) {
113 BitmapRevFilter filter = newRevFilter(seen, bitmapResult);
114 walker.setRevFilter(filter);
115
116 while (walker.next() != null) {
117
118
119 pm.update(1);
120 }
121
122 RevObject ro;
123 while ((ro = walker.nextObject()) != null) {
124 bitmapResult.add(ro, ro.getType());
125 pm.update(1);
126 }
127 countOfBitmapIndexMisses += filter.getCountOfLoadedCommits();
128 }
129
130 return bitmapResult;
131 }
132
133 void reset() {
134 walker.reset();
135 }
136
137 static BitmapRevFilter newRevFilter(
138 final BitmapBuilder seen, final BitmapBuilder bitmapResult) {
139 if (seen != null) {
140 return new BitmapRevFilter() {
141 protected boolean load(RevCommit cmit) {
142 if (seen.contains(cmit))
143 return false;
144 return bitmapResult.add(cmit, Constants.OBJ_COMMIT);
145 }
146 };
147 }
148 return new BitmapRevFilter() {
149 @Override
150 protected boolean load(RevCommit cmit) {
151 return bitmapResult.add(cmit, Constants.OBJ_COMMIT);
152 }
153 };
154 }
155
156 static abstract class BitmapRevFilter extends RevFilter {
157 private long countOfLoadedCommits;
158
159 protected abstract boolean load(RevCommit cmit);
160
161 @Override
162 public final boolean include(RevWalk walker, RevCommit cmit) {
163 if (load(cmit)) {
164 countOfLoadedCommits++;
165 return true;
166 }
167 for (RevCommit p : cmit.getParents())
168 p.add(RevFlag.SEEN);
169 return false;
170 }
171
172 @Override
173 public final RevFilter clone() {
174 return this;
175 }
176
177 @Override
178 public final boolean requiresCommitBody() {
179 return false;
180 }
181
182 long getCountOfLoadedCommits() {
183 return countOfLoadedCommits;
184 }
185 }
186 }