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 static org.junit.Assert.assertEquals;
47 import static org.junit.Assert.assertTrue;
48
49 import java.io.IOException;
50 import java.util.ArrayList;
51 import java.util.Arrays;
52 import java.util.Collections;
53 import java.util.List;
54 import java.util.Set;
55
56 import org.eclipse.jgit.internal.storage.file.GcTestCase;
57 import org.eclipse.jgit.internal.storage.file.PackBitmapIndexBuilder;
58 import org.eclipse.jgit.internal.storage.pack.ObjectToPack;
59 import org.eclipse.jgit.internal.storage.pack.PackWriterBitmapPreparer;
60 import org.eclipse.jgit.internal.storage.pack.PackWriterBitmapPreparer.BitmapCommit;
61 import org.eclipse.jgit.junit.TestRepository.BranchBuilder;
62 import org.eclipse.jgit.junit.TestRepository.CommitBuilder;
63 import org.eclipse.jgit.lib.Constants;
64 import org.eclipse.jgit.lib.NullProgressMonitor;
65 import org.eclipse.jgit.lib.ObjectId;
66 import org.eclipse.jgit.revwalk.RevCommit;
67 import org.eclipse.jgit.storage.pack.PackConfig;
68 import org.junit.Test;
69
70 public class GcCommitSelectionTest extends GcTestCase {
71
72 @Test
73 public void testBitmapSpansNoMerges() throws Exception {
74
75
76
77
78
79
80
81 int[][] bitmapCounts = {
82 { 1, 1 }, { 50, 50 }, { 99, 99 }, { 100, 100 }, { 101, 100 },
83 { 200, 100 }, { 201, 100 }, { 299, 100 }, { 300, 101 },
84 { 301, 101 }, { 401, 101 }, { 499, 101 }, { 500, 102 }, };
85 int currentCommits = 0;
86 BranchBuilder bb = tr.branch("refs/heads/main");
87
88 for (int[] counts : bitmapCounts) {
89 int nextCommitCount = counts[0];
90 int expectedBitmapCount = counts[1];
91 assertTrue(nextCommitCount > currentCommits);
92 for (int i = currentCommits; i < nextCommitCount; i++) {
93 String str = "A" + i;
94 bb.commit().message(str).add(str, str).create();
95 }
96 currentCommits = nextCommitCount;
97
98 gc.setPackExpireAgeMillis(0);
99 gc.setExpireAgeMillis(0);
100 gc.gc();
101 assertEquals(currentCommits * 3,
102 gc.getStatistics().numberOfPackedObjects);
103 assertEquals(currentCommits + " commits: ", expectedBitmapCount,
104 gc.getStatistics().numberOfBitmaps);
105 }
106 }
107
108 @Test
109 public void testBitmapSpansWithMerges() throws Exception {
110
111
112
113
114
115
116 List<Integer> merges = Arrays.asList(Integer.valueOf(55),
117 Integer.valueOf(115), Integer.valueOf(175),
118 Integer.valueOf(235));
119
120
121
122
123
124
125
126 int[][] bitmapCounts = {
127 { 1, 1 }, { 55, 55 }, { 56, 57 },
128 { 99, 100 },
129 { 100, 100 },
130 { 116, 100 },
131 { 176, 101 },
132 { 213, 101 },
133 { 214, 102 },
134 { 236, 102 },
135 { 273, 102 },
136 { 274, 103 },
137 { 334, 103 },
138 { 335, 104 },
139 { 435, 104 },
140 { 436, 104 },
141 };
142
143 int currentCommits = 0;
144 BranchBuilder bb = tr.branch("refs/heads/main");
145
146 for (int[] counts : bitmapCounts) {
147 int nextCommitCount = counts[0];
148 int expectedBitmapCount = counts[1];
149 assertTrue(nextCommitCount > currentCommits);
150 for (int i = currentCommits; i < nextCommitCount; i++) {
151 String str = "A" + i;
152 if (!merges.contains(Integer.valueOf(i))) {
153 bb.commit().message(str).add(str, str).create();
154 } else {
155 BranchBuilder bbN = tr.branch("refs/heads/A" + i);
156 bb.commit().message(str).add(str, str)
157 .parent(bbN.commit().create()).create();
158 }
159 }
160 currentCommits = nextCommitCount;
161
162 gc.setPackExpireAgeMillis(0);
163 gc.setExpireAgeMillis(0);
164 gc.gc();
165 assertEquals(currentCommits + " commits: ", expectedBitmapCount,
166 gc.getStatistics().numberOfBitmaps);
167 }
168 }
169
170 @Test
171 public void testBitmapsForExcessiveBranches() throws Exception {
172 int oneDayInSeconds = 60 * 60 * 24;
173
174
175 BranchBuilder bbA = tr.branch("refs/heads/A");
176 for (int i = 0; i < 1001; i++) {
177 String msg = "A" + i;
178 bbA.commit().message(msg).add(msg, msg).create();
179 }
180
181 tr.tick(oneDayInSeconds * 90);
182 BranchBuilder bbB = tr.branch("refs/heads/B");
183 for (int i = 0; i < 1001; i++) {
184 String msg = "B" + i;
185 bbB.commit().message(msg).add(msg, msg).create();
186 }
187
188 for (int i = 0; i < 100; i++) {
189 BranchBuilder bb = tr.branch("refs/heads/N" + i);
190 String msg = "singlecommit" + i;
191 bb.commit().message(msg).add(msg, msg).create();
192 }
193
194 tr.tick(oneDayInSeconds);
195
196
197
198 final int commitsForSparseBranch = 1 + (1001 / 200);
199 final int commitsForFullBranch = 100 + (901 / 200);
200 final int commitsForShallowBranches = 100;
201
202
203 gc.setPackExpireAgeMillis(0);
204 gc.setExpireAgeMillis(0);
205 gc.gc();
206 assertEquals(
207 commitsForSparseBranch + commitsForFullBranch
208 + commitsForShallowBranches,
209 gc.getStatistics().numberOfBitmaps);
210 }
211
212 @Test
213 public void testSelectionOrderingWithChains() throws Exception {
214
215
216
217
218
219
220
221
222 BranchBuilder bb = tr.branch("refs/heads/main");
223 RevCommit m0 = addCommit(bb, "m0");
224 RevCommit m1 = addCommit(bb, "m1", m0);
225 RevCommit m2 = addCommit(bb, "m2", m1);
226 RevCommit b3 = addCommit(bb, "b3", m1);
227 RevCommit m4 = addCommit(bb, "m4", m2);
228 RevCommit b5 = addCommit(bb, "m5", b3);
229 RevCommit m6 = addCommit(bb, "m6", m4);
230 RevCommit b7 = addCommit(bb, "m7", b5);
231 RevCommit m8 = addCommit(bb, "m8", m6, b7);
232 RevCommit m9 = addCommit(bb, "m9", m8);
233
234 List<RevCommit> commits = Arrays.asList(m0, m1, m2, b3, m4, b5, m6, b7,
235 m8, m9);
236 PackWriterBitmapPreparer preparer = newPeparer(m9, commits);
237 List<BitmapCommit> selection = new ArrayList<>(
238 preparer.selectCommits(commits.size()));
239
240
241 String[] expected = { m0.name(), m1.name(), m2.name(), m4.name(),
242 m6.name(), m8.name(), m9.name(), b3.name(), b5.name(),
243 b7.name() };
244 assertEquals(expected.length, selection.size());
245 for (int i = 0; i < expected.length; i++) {
246 assertEquals("Entry " + i, expected[i], selection.get(i).getName());
247 }
248 }
249
250 private RevCommit addCommit(BranchBuilder bb, String msg,
251 RevCommit... parents) throws Exception {
252 CommitBuilder commit = bb.commit().message(msg).add(msg, msg).tick(1)
253 .noParents();
254 for (RevCommit parent : parents) {
255 commit.parent(parent);
256 }
257 return commit.create();
258 }
259
260 private PackWriterBitmapPreparer newPeparer(RevCommit want,
261 List<RevCommit> commits)
262 throws IOException {
263 List<ObjectToPack> objects = new ArrayList<>(commits.size());
264 for (RevCommit commit : commits) {
265 objects.add(new ObjectToPack(commit, Constants.OBJ_COMMIT));
266 }
267 Set<ObjectId> wants = Collections.singleton((ObjectId) want);
268 PackConfig config = new PackConfig();
269 PackBitmapIndexBuilder builder = new PackBitmapIndexBuilder(objects);
270 return new PackWriterBitmapPreparer(
271 tr.getRepository().newObjectReader(), builder,
272 NullProgressMonitor.INSTANCE, wants, config);
273 }
274 }