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 package org.eclipse.jgit.transport;
44
45 import static org.eclipse.jgit.lib.MoreAsserts.assertThrows;
46 import static org.hamcrest.Matchers.containsString;
47 import static org.junit.Assert.assertFalse;
48 import static org.junit.Assert.assertThat;
49 import static org.junit.Assert.assertTrue;
50
51 import java.util.Collections;
52
53 import org.eclipse.jgit.errors.TransportException;
54 import org.eclipse.jgit.internal.storage.dfs.DfsGarbageCollector;
55 import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription;
56 import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
57 import org.eclipse.jgit.junit.TestRepository;
58 import org.eclipse.jgit.lib.NullProgressMonitor;
59 import org.eclipse.jgit.lib.Repository;
60 import org.eclipse.jgit.revwalk.RevBlob;
61 import org.eclipse.jgit.revwalk.RevCommit;
62 import org.eclipse.jgit.transport.UploadPack.RequestPolicy;
63 import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException;
64 import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException;
65 import org.eclipse.jgit.transport.resolver.UploadPackFactory;
66 import org.junit.After;
67 import org.junit.Before;
68 import org.junit.Rule;
69 import org.junit.Test;
70 import org.junit.rules.ExpectedException;
71
72
73
74
75
76
77
78
79
80 public class UploadPackReachabilityTest {
81
82 @Rule
83 public ExpectedException thrown = ExpectedException.none();
84
85 private URIish uri;
86
87 private TestProtocol<Object> testProtocol;
88
89 private Object ctx = new Object();
90
91 private InMemoryRepository server;
92
93 private InMemoryRepository client;
94
95 private TestRepository<InMemoryRepository> remote;
96
97 @Before
98 public void setUp() throws Exception {
99 server = newRepo("server");
100 client = newRepo("client");
101
102 remote = new TestRepository<>(server);
103 }
104
105 @After
106 public void tearDown() {
107 Transport.unregister(testProtocol);
108 }
109
110 @Test
111 public void testFetchUnreachableBlobWithBitmap() throws Exception {
112 RevBlob blob = remote.blob("foo");
113 remote.commit(remote.tree(remote.file("foo", blob)));
114 generateBitmaps(server);
115
116 testProtocol = generateReachableCommitUploadPackProtocol();
117 uri = testProtocol.register(ctx, server);
118
119 assertFalse(client.getObjectDatabase().has(blob.toObjectId()));
120
121 try (Transport tn = testProtocol.open(uri, client, "server")) {
122 TransportException e = assertThrows(TransportException.class,
123 () -> tn.fetch(NullProgressMonitor.INSTANCE, Collections
124 .singletonList(new RefSpec(blob.name()))));
125 assertThat(e.getMessage(),
126 containsString("want " + blob.name() + " not valid"));
127 }
128 }
129
130 @Test
131 public void testFetchReachableBlobWithoutBitmap() throws Exception {
132 RevBlob blob = remote.blob("foo");
133 RevCommit commit = remote.commit(remote.tree(remote.file("foo", blob)));
134 remote.update("master", commit);
135
136 testProtocol = generateReachableCommitUploadPackProtocol();
137 uri = testProtocol.register(ctx, server);
138
139 assertFalse(client.getObjectDatabase().has(blob.toObjectId()));
140
141 try (Transport tn = testProtocol.open(uri, client, "server")) {
142 TransportException e = assertThrows(TransportException.class,
143 () -> tn.fetch(NullProgressMonitor.INSTANCE, Collections
144 .singletonList(new RefSpec(blob.name()))));
145 assertThat(e.getMessage(),
146 containsString(
147 "want " + blob.name() + " not valid"));
148 }
149 }
150
151 @Test
152 public void testFetchReachableBlobWithoutBitmapButFilterAllowed() throws Exception {
153 InMemoryRepository server2 = newRepo("server2");
154 try (TestRepository<InMemoryRepository> remote2 = new TestRepository<>(
155 server2)) {
156 RevBlob blob = remote2.blob("foo");
157 RevCommit commit = remote2.commit(remote2.tree(remote2.file("foo", blob)));
158 remote2.update("master", commit);
159
160 server2.getConfig().setBoolean("uploadpack", null, "allowfilter",
161 true);
162
163 testProtocol = new TestProtocol<>((Object req, Repository db) -> {
164 UploadPack up = new UploadPack(db);
165 up.setRequestPolicy(RequestPolicy.REACHABLE_COMMIT);
166 return up;
167 }, null);
168 uri = testProtocol.register(ctx, server2);
169
170 assertFalse(client.getObjectDatabase().has(blob.toObjectId()));
171
172 try (Transport tn = testProtocol.open(uri, client, "server2")) {
173 tn.fetch(NullProgressMonitor.INSTANCE,
174 Collections.singletonList(new RefSpec(blob.name())));
175 assertTrue(client.getObjectDatabase().has(blob.toObjectId()));
176 }
177 }
178 }
179
180 @Test
181 public void testFetchUnreachableBlobWithoutBitmap() throws Exception {
182 RevBlob blob = remote.blob("foo");
183 remote.commit(remote.tree(remote.file("foo", blob)));
184
185 testProtocol = generateReachableCommitUploadPackProtocol();
186 uri = testProtocol.register(ctx, server);
187
188 assertFalse(client.getObjectDatabase().has(blob.toObjectId()));
189
190 try (Transport tn = testProtocol.open(uri, client, "server")) {
191 TransportException e = assertThrows(TransportException.class, () ->
192 tn.fetch(NullProgressMonitor.INSTANCE,
193 Collections.singletonList(new RefSpec(blob.name()))));
194 assertThat(e.getMessage(),
195 containsString("want " + blob.name() + " not valid"));
196 }
197 }
198
199 @Test
200 public void testFetchReachableBlobWithBitmap() throws Exception {
201 RevBlob blob = remote.blob("foo");
202 RevCommit commit = remote.commit(remote.tree(remote.file("foo", blob)));
203 remote.update("master", commit);
204 generateBitmaps(server);
205
206 testProtocol = generateReachableCommitUploadPackProtocol();
207 uri = testProtocol.register(ctx, server);
208
209 assertFalse(client.getObjectDatabase().has(blob.toObjectId()));
210
211 try (Transport tn = testProtocol.open(uri, client, "server")) {
212 tn.fetch(NullProgressMonitor.INSTANCE,
213 Collections.singletonList(new RefSpec(blob.name())));
214 assertTrue(client.getObjectDatabase().has(blob.toObjectId()));
215 }
216 }
217
218 @Test
219 public void testFetchReachableCommitWithBitmap() throws Exception {
220 RevCommit commit = remote
221 .commit(remote.tree(remote.file("foo", remote.blob("foo"))));
222 remote.update("master", commit);
223 generateBitmaps(server);
224
225 testProtocol = generateReachableCommitUploadPackProtocol();
226 uri = testProtocol.register(ctx, server);
227
228 assertFalse(client.getObjectDatabase().has(commit.toObjectId()));
229
230 try (Transport tn = testProtocol.open(uri, client, "server")) {
231 tn.fetch(NullProgressMonitor.INSTANCE,
232 Collections.singletonList(new RefSpec(commit.name())));
233 assertTrue(client.getObjectDatabase().has(commit.toObjectId()));
234 }
235 }
236
237 @Test
238 public void testFetchReachableCommitWithoutBitmap() throws Exception {
239 RevCommit commit = remote
240 .commit(remote.tree(remote.file("foo", remote.blob("foo"))));
241 remote.update("master", commit);
242 generateBitmaps(server);
243
244 testProtocol = generateReachableCommitUploadPackProtocol();
245 uri = testProtocol.register(ctx, server);
246
247 assertFalse(client.getObjectDatabase().has(commit.toObjectId()));
248
249 try (Transport tn = testProtocol.open(uri, client, "server")) {
250 tn.fetch(NullProgressMonitor.INSTANCE,
251 Collections.singletonList(new RefSpec(commit.name())));
252 assertTrue(client.getObjectDatabase().has(commit.toObjectId()));
253 }
254 }
255
256 @Test
257 public void testFetchUnreachableCommitWithBitmap() throws Exception {
258 RevCommit commit = remote
259 .commit(remote.tree(remote.file("foo", remote.blob("foo"))));
260 generateBitmaps(server);
261
262 testProtocol = generateReachableCommitUploadPackProtocol();
263 uri = testProtocol.register(ctx, server);
264
265 assertFalse(client.getObjectDatabase().has(commit.toObjectId()));
266
267 try (Transport tn = testProtocol.open(uri, client, "server")) {
268 TransportException e = assertThrows(TransportException.class,
269 () -> tn.fetch(NullProgressMonitor.INSTANCE,
270 Collections.singletonList(new RefSpec(commit.name()))));
271 assertThat(e.getMessage(),
272 containsString("want " + commit.name() + " not valid"));
273 }
274 }
275
276 @Test
277 public void testFetchUnreachableCommitWithoutBitmap() throws Exception {
278 RevCommit commit = remote
279 .commit(remote.tree(remote.file("foo", remote.blob("foo"))));
280
281 testProtocol = generateReachableCommitUploadPackProtocol();
282 uri = testProtocol.register(ctx, server);
283
284 assertFalse(client.getObjectDatabase().has(commit.toObjectId()));
285
286 try (Transport tn = testProtocol.open(uri, client, "server")) {
287 TransportException e = assertThrows(TransportException.class,
288 () -> tn.fetch(NullProgressMonitor.INSTANCE, Collections
289 .singletonList(new RefSpec(commit.name()))));
290 assertThat(e.getMessage(),
291 containsString("want " + commit.name() + " not valid"));
292 }
293 }
294
295 private static InMemoryRepository newRepo(String name) {
296 return new InMemoryRepository(new DfsRepositoryDescription(name));
297 }
298
299 private void generateBitmaps(InMemoryRepository repo) throws Exception {
300 new DfsGarbageCollector(repo).pack(null);
301 repo.scanForRepoChanges();
302 }
303
304 private static TestProtocol<Object> generateReachableCommitUploadPackProtocol() {
305 return new TestProtocol<>(new UploadPackFactory<Object>() {
306 @Override
307 public UploadPack create(Object req, Repository db)
308 throws ServiceNotEnabledException,
309 ServiceNotAuthorizedException {
310 UploadPack up = new UploadPack(db);
311 up.setRequestPolicy(RequestPolicy.REACHABLE_COMMIT);
312 return up;
313 }
314 }, null);
315 }
316 }