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