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