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.http.test;
45
46 import static org.eclipse.jgit.util.HttpSupport.HDR_CONTENT_ENCODING;
47 import static org.eclipse.jgit.util.HttpSupport.HDR_CONTENT_LENGTH;
48 import static org.eclipse.jgit.util.HttpSupport.HDR_CONTENT_TYPE;
49 import static org.junit.Assert.assertEquals;
50 import static org.junit.Assert.assertFalse;
51 import static org.junit.Assert.assertNotNull;
52 import static org.junit.Assert.assertNull;
53 import static org.junit.Assert.assertTrue;
54 import static org.junit.Assert.fail;
55
56 import java.io.IOException;
57 import java.io.PrintWriter;
58 import java.net.URISyntaxException;
59 import java.nio.charset.StandardCharsets;
60 import java.util.Arrays;
61 import java.util.Collection;
62 import java.util.Collections;
63 import java.util.EnumSet;
64 import java.util.List;
65 import java.util.Map;
66
67 import javax.servlet.DispatcherType;
68 import javax.servlet.Filter;
69 import javax.servlet.FilterChain;
70 import javax.servlet.FilterConfig;
71 import javax.servlet.ServletException;
72 import javax.servlet.ServletRequest;
73 import javax.servlet.ServletResponse;
74 import javax.servlet.http.HttpServletRequest;
75 import javax.servlet.http.HttpServletResponse;
76
77 import org.eclipse.jetty.servlet.FilterHolder;
78 import org.eclipse.jetty.servlet.ServletContextHandler;
79 import org.eclipse.jetty.servlet.ServletHolder;
80 import org.eclipse.jgit.errors.RemoteRepositoryException;
81 import org.eclipse.jgit.errors.RepositoryNotFoundException;
82 import org.eclipse.jgit.errors.TransportException;
83 import org.eclipse.jgit.http.server.GitServlet;
84 import org.eclipse.jgit.internal.JGitText;
85 import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription;
86 import org.eclipse.jgit.junit.TestRepository;
87 import org.eclipse.jgit.junit.TestRng;
88 import org.eclipse.jgit.junit.http.AccessEvent;
89 import org.eclipse.jgit.junit.http.AppServer;
90 import org.eclipse.jgit.junit.http.HttpTestCase;
91 import org.eclipse.jgit.lib.ConfigConstants;
92 import org.eclipse.jgit.lib.Constants;
93 import org.eclipse.jgit.lib.NullProgressMonitor;
94 import org.eclipse.jgit.lib.ObjectId;
95 import org.eclipse.jgit.lib.ObjectIdRef;
96 import org.eclipse.jgit.lib.ObjectInserter;
97 import org.eclipse.jgit.lib.Ref;
98 import org.eclipse.jgit.lib.ReflogEntry;
99 import org.eclipse.jgit.lib.ReflogReader;
100 import org.eclipse.jgit.lib.Repository;
101 import org.eclipse.jgit.lib.StoredConfig;
102 import org.eclipse.jgit.revwalk.RevBlob;
103 import org.eclipse.jgit.revwalk.RevCommit;
104 import org.eclipse.jgit.transport.FetchConnection;
105 import org.eclipse.jgit.transport.HttpTransport;
106 import org.eclipse.jgit.transport.RemoteRefUpdate;
107 import org.eclipse.jgit.transport.Transport;
108 import org.eclipse.jgit.transport.TransportHttp;
109 import org.eclipse.jgit.transport.URIish;
110 import org.eclipse.jgit.transport.http.HttpConnectionFactory;
111 import org.eclipse.jgit.transport.http.JDKHttpConnectionFactory;
112 import org.eclipse.jgit.transport.http.apache.HttpClientConnectionFactory;
113 import org.eclipse.jgit.transport.resolver.RepositoryResolver;
114 import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException;
115 import org.junit.Before;
116 import org.junit.Test;
117 import org.junit.runner.RunWith;
118 import org.junit.runners.Parameterized;
119 import org.junit.runners.Parameterized.Parameters;
120
121 @RunWith(Parameterized.class)
122 public class SmartClientSmartServerTest extends HttpTestCase {
123 private static final String HDR_TRANSFER_ENCODING = "Transfer-Encoding";
124
125 private Repository remoteRepository;
126
127 private URIish remoteURI;
128
129 private URIish brokenURI;
130
131 private RevBlob A_txt;
132
133 private RevCommit A, B;
134
135 @Parameters
136 public static Collection<Object[]> data() {
137
138 return Arrays.asList(new Object[][] {
139 { new JDKHttpConnectionFactory() },
140 { new HttpClientConnectionFactory() } });
141 }
142
143 public SmartClientSmartServerTest(HttpConnectionFactory cf) {
144 HttpTransport.setConnectionFactory(cf);
145 }
146
147 @Before
148 public void setUp() throws Exception {
149 super.setUp();
150
151 final TestRepository<Repository> src = createTestRepository();
152 final String srcName = src.getRepository().getDirectory().getName();
153 src.getRepository()
154 .getConfig()
155 .setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
156 ConfigConstants.CONFIG_KEY_LOGALLREFUPDATES, true);
157
158 ServletContextHandler app = server.addContext("/git");
159 GitServlet gs = new GitServlet();
160 gs.setRepositoryResolver(new TestRepoResolver(src, srcName));
161 app.addServlet(new ServletHolder(gs), "/*");
162
163 ServletContextHandler broken = server.addContext("/bad");
164 broken.addFilter(new FilterHolder(new Filter() {
165 public void doFilter(ServletRequest request,
166 ServletResponse response, FilterChain chain)
167 throws IOException, ServletException {
168 final HttpServletResponse r = (HttpServletResponse) response;
169 r.setContentType("text/plain");
170 r.setCharacterEncoding("UTF-8");
171 PrintWriter w = r.getWriter();
172 w.print("OK");
173 w.close();
174 }
175
176 public void init(FilterConfig filterConfig) throws ServletException {
177
178 }
179
180 public void destroy() {
181
182 }
183 }), "/" + srcName + "/git-upload-pack",
184 EnumSet.of(DispatcherType.REQUEST));
185 broken.addServlet(new ServletHolder(gs), "/*");
186
187 server.setUp();
188
189 remoteRepository = src.getRepository();
190 remoteURI = toURIish(app, srcName);
191 brokenURI = toURIish(broken, srcName);
192
193 A_txt = src.blob("A");
194 A = src.commit().add("A_txt", A_txt).create();
195 B = src.commit().parent(A).add("A_txt", "C").add("B", "B").create();
196 src.update(master, B);
197
198 src.update("refs/garbage/a/very/long/ref/name/to/compress", B);
199 }
200
201 @Test
202 public void testListRemote() throws IOException {
203 Repository dst = createBareRepository();
204
205 assertEquals("http", remoteURI.getScheme());
206
207 Map<String, Ref> map;
208 try (Transport t = Transport.open(dst, remoteURI)) {
209
210
211
212
213 assertTrue("isa TransportHttp", t instanceof TransportHttp);
214 assertTrue("isa HttpTransport", t instanceof HttpTransport);
215
216 FetchConnection c = t.openFetch();
217 try {
218 map = c.getRefsMap();
219 } finally {
220 c.close();
221 }
222 }
223
224 assertNotNull("have map of refs", map);
225 assertEquals(3, map.size());
226
227 assertNotNull("has " + master, map.get(master));
228 assertEquals(B, map.get(master).getObjectId());
229
230 assertNotNull("has " + Constants.HEAD, map.get(Constants.HEAD));
231 assertEquals(B, map.get(Constants.HEAD).getObjectId());
232
233 List<AccessEvent> requests = getRequests();
234 assertEquals(1, requests.size());
235
236 AccessEvent info = requests.get(0);
237 assertEquals("GET", info.getMethod());
238 assertEquals(join(remoteURI, "info/refs"), info.getPath());
239 assertEquals(1, info.getParameters().size());
240 assertEquals("git-upload-pack", info.getParameter("service"));
241 assertEquals(200, info.getStatus());
242 assertEquals("application/x-git-upload-pack-advertisement", info
243 .getResponseHeader(HDR_CONTENT_TYPE));
244 assertEquals("gzip", info.getResponseHeader(HDR_CONTENT_ENCODING));
245 }
246
247 @Test
248 public void testListRemote_BadName() throws IOException, URISyntaxException {
249 Repository dst = createBareRepository();
250 URIish uri = new URIish(this.remoteURI.toString() + ".invalid");
251 try (Transport t = Transport.open(dst, uri)) {
252 try {
253 t.openFetch();
254 fail("fetch connection opened");
255 } catch (RemoteRepositoryException notFound) {
256 assertEquals(uri + ": Git repository not found",
257 notFound.getMessage());
258 }
259 }
260
261 List<AccessEvent> requests = getRequests();
262 assertEquals(1, requests.size());
263
264 AccessEvent info = requests.get(0);
265 assertEquals("GET", info.getMethod());
266 assertEquals(join(uri, "info/refs"), info.getPath());
267 assertEquals(1, info.getParameters().size());
268 assertEquals("git-upload-pack", info.getParameter("service"));
269 assertEquals(200, info.getStatus());
270 assertEquals("application/x-git-upload-pack-advertisement",
271 info.getResponseHeader(HDR_CONTENT_TYPE));
272 }
273
274 @Test
275 public void testInitialClone_Small() throws Exception {
276 Repository dst = createBareRepository();
277 assertFalse(dst.hasObject(A_txt));
278
279 try (Transport t = Transport.open(dst, remoteURI)) {
280 t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
281 }
282
283 assertTrue(dst.hasObject(A_txt));
284 assertEquals(B, dst.exactRef(master).getObjectId());
285 fsck(dst, B);
286
287 List<AccessEvent> requests = getRequests();
288 assertEquals(2, requests.size());
289
290 AccessEvent info = requests.get(0);
291 assertEquals("GET", info.getMethod());
292 assertEquals(join(remoteURI, "info/refs"), info.getPath());
293 assertEquals(1, info.getParameters().size());
294 assertEquals("git-upload-pack", info.getParameter("service"));
295 assertEquals(200, info.getStatus());
296 assertEquals("application/x-git-upload-pack-advertisement", info
297 .getResponseHeader(HDR_CONTENT_TYPE));
298 assertEquals("gzip", info.getResponseHeader(HDR_CONTENT_ENCODING));
299
300 AccessEvent service = requests.get(1);
301 assertEquals("POST", service.getMethod());
302 assertEquals(join(remoteURI, "git-upload-pack"), service.getPath());
303 assertEquals(0, service.getParameters().size());
304 assertNotNull("has content-length", service
305 .getRequestHeader(HDR_CONTENT_LENGTH));
306 assertNull("not chunked", service
307 .getRequestHeader(HDR_TRANSFER_ENCODING));
308
309 assertEquals(200, service.getStatus());
310 assertEquals("application/x-git-upload-pack-result", service
311 .getResponseHeader(HDR_CONTENT_TYPE));
312 }
313
314 @Test
315 public void testFetch_FewLocalCommits() throws Exception {
316
317
318 TestRepository dst = createTestRepository();
319 try (Transport t = Transport.open(dst.getRepository(), remoteURI)) {
320 t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
321 }
322 assertEquals(B, dst.getRepository().exactRef(master).getObjectId());
323 List<AccessEvent> cloneRequests = getRequests();
324
325
326 TestRepository.BranchBuilder b = dst.branch(master);
327 for (int i = 0; i < 4; i++)
328 b.commit().tick(3600 ).message("c" + i).create();
329
330
331
332 b = new TestRepository<Repository>(remoteRepository).branch(master);
333 RevCommit Z = b.commit().message("Z").create();
334
335
336
337 try (Transport t = Transport.open(dst.getRepository(), remoteURI)) {
338 t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
339 }
340 assertEquals(Z, dst.getRepository().exactRef(master).getObjectId());
341
342 List<AccessEvent> requests = getRequests();
343 requests.removeAll(cloneRequests);
344 assertEquals(2, requests.size());
345
346 AccessEvent info = requests.get(0);
347 assertEquals("GET", info.getMethod());
348 assertEquals(join(remoteURI, "info/refs"), info.getPath());
349 assertEquals(1, info.getParameters().size());
350 assertEquals("git-upload-pack", info.getParameter("service"));
351 assertEquals(200, info.getStatus());
352 assertEquals("application/x-git-upload-pack-advertisement",
353 info.getResponseHeader(HDR_CONTENT_TYPE));
354
355
356
357 AccessEvent service = requests.get(1);
358 assertEquals("POST", service.getMethod());
359 assertEquals(join(remoteURI, "git-upload-pack"), service.getPath());
360 assertEquals(0, service.getParameters().size());
361 assertNotNull("has content-length",
362 service.getRequestHeader(HDR_CONTENT_LENGTH));
363 assertNull("not chunked",
364 service.getRequestHeader(HDR_TRANSFER_ENCODING));
365
366 assertEquals(200, service.getStatus());
367 assertEquals("application/x-git-upload-pack-result",
368 service.getResponseHeader(HDR_CONTENT_TYPE));
369 }
370
371 @Test
372 public void testFetch_TooManyLocalCommits() throws Exception {
373
374
375 TestRepository dst = createTestRepository();
376 try (Transport t = Transport.open(dst.getRepository(), remoteURI)) {
377 t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
378 }
379 assertEquals(B, dst.getRepository().exactRef(master).getObjectId());
380 List<AccessEvent> cloneRequests = getRequests();
381
382
383
384
385
386 TestRepository.BranchBuilder b = dst.branch(master);
387 for (int i = 0; i < 32 - 1; i++)
388 b.commit().tick(3600 ).message("c" + i).create();
389
390
391
392 b = new TestRepository<Repository>(remoteRepository).branch(master);
393 RevCommit Z = b.commit().message("Z").create();
394
395
396
397 try (Transport t = Transport.open(dst.getRepository(), remoteURI)) {
398 t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
399 }
400 assertEquals(Z, dst.getRepository().exactRef(master).getObjectId());
401
402 List<AccessEvent> requests = getRequests();
403 requests.removeAll(cloneRequests);
404 assertEquals(3, requests.size());
405
406 AccessEvent info = requests.get(0);
407 assertEquals("GET", info.getMethod());
408 assertEquals(join(remoteURI, "info/refs"), info.getPath());
409 assertEquals(1, info.getParameters().size());
410 assertEquals("git-upload-pack", info.getParameter("service"));
411 assertEquals(200, info.getStatus());
412 assertEquals("application/x-git-upload-pack-advertisement", info
413 .getResponseHeader(HDR_CONTENT_TYPE));
414
415
416
417
418 AccessEvent service = requests.get(1);
419 assertEquals("POST", service.getMethod());
420 assertEquals(join(remoteURI, "git-upload-pack"), service.getPath());
421 assertEquals(0, service.getParameters().size());
422 assertNotNull("has content-length", service
423 .getRequestHeader(HDR_CONTENT_LENGTH));
424 assertNull("not chunked", service
425 .getRequestHeader(HDR_TRANSFER_ENCODING));
426
427 assertEquals(200, service.getStatus());
428 assertEquals("application/x-git-upload-pack-result", service
429 .getResponseHeader(HDR_CONTENT_TYPE));
430
431 service = requests.get(2);
432 assertEquals("POST", service.getMethod());
433 assertEquals(join(remoteURI, "git-upload-pack"), service.getPath());
434 assertEquals(0, service.getParameters().size());
435 assertNotNull("has content-length", service
436 .getRequestHeader(HDR_CONTENT_LENGTH));
437 assertNull("not chunked", service
438 .getRequestHeader(HDR_TRANSFER_ENCODING));
439
440 assertEquals(200, service.getStatus());
441 assertEquals("application/x-git-upload-pack-result", service
442 .getResponseHeader(HDR_CONTENT_TYPE));
443 }
444
445 @Test
446 public void testInitialClone_BrokenServer() throws Exception {
447 Repository dst = createBareRepository();
448 assertFalse(dst.hasObject(A_txt));
449
450 try (Transport t = Transport.open(dst, brokenURI)) {
451 try {
452 t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
453 fail("fetch completed despite upload-pack being broken");
454 } catch (TransportException err) {
455 String exp = brokenURI + ": expected"
456 + " Content-Type application/x-git-upload-pack-result;"
457 + " received Content-Type text/plain; charset=UTF-8";
458 assertEquals(exp, err.getMessage());
459 }
460 }
461
462 List<AccessEvent> requests = getRequests();
463 assertEquals(2, requests.size());
464
465 AccessEvent info = requests.get(0);
466 assertEquals("GET", info.getMethod());
467 assertEquals(join(brokenURI, "info/refs"), info.getPath());
468 assertEquals(1, info.getParameters().size());
469 assertEquals("git-upload-pack", info.getParameter("service"));
470 assertEquals(200, info.getStatus());
471 assertEquals("application/x-git-upload-pack-advertisement", info
472 .getResponseHeader(HDR_CONTENT_TYPE));
473
474 AccessEvent service = requests.get(1);
475 assertEquals("POST", service.getMethod());
476 assertEquals(join(brokenURI, "git-upload-pack"), service.getPath());
477 assertEquals(0, service.getParameters().size());
478 assertEquals(200, service.getStatus());
479 assertEquals("text/plain; charset=UTF-8",
480 service.getResponseHeader(HDR_CONTENT_TYPE));
481 }
482
483 @Test
484 public void testInvalidWant() throws Exception {
485 @SuppressWarnings("resource")
486 ObjectId id = new ObjectInserter.Formatter().idFor(Constants.OBJ_BLOB,
487 "testInvalidWant".getBytes(StandardCharsets.UTF_8));
488
489 Repository dst = createBareRepository();
490 try (Transport t = Transport.open(dst, remoteURI);
491 FetchConnection c = t.openFetch()) {
492 Ref want = new ObjectIdRef.Unpeeled(Ref.Storage.NETWORK, id.name(),
493 id);
494 c.fetch(NullProgressMonitor.INSTANCE, Collections.singleton(want),
495 Collections.<ObjectId> emptySet());
496 fail("Server accepted want " + id.name());
497 } catch (TransportException err) {
498 assertEquals("want " + id.name() + " not valid", err.getMessage());
499 }
500 }
501
502 @Test
503 public void testFetch_RefsUnreadableOnUpload() throws Exception {
504 AppServer noRefServer = new AppServer();
505 try {
506 final String repoName = "refs-unreadable";
507 RefsUnreadableInMemoryRepository badRefsRepo = new RefsUnreadableInMemoryRepository(
508 new DfsRepositoryDescription(repoName));
509 final TestRepository<Repository> repo = new TestRepository<Repository>(
510 badRefsRepo);
511
512 ServletContextHandler app = noRefServer.addContext("/git");
513 GitServlet gs = new GitServlet();
514 gs.setRepositoryResolver(new TestRepoResolver(repo, repoName));
515 app.addServlet(new ServletHolder(gs), "/*");
516 noRefServer.setUp();
517
518 RevBlob A2_txt = repo.blob("A2");
519 RevCommit A2 = repo.commit().add("A2_txt", A2_txt).create();
520 RevCommit B2 = repo.commit().parent(A2).add("A2_txt", "C2")
521 .add("B2", "B2").create();
522 repo.update(master, B2);
523
524 URIish badRefsURI = new URIish(noRefServer.getURI()
525 .resolve(app.getContextPath() + "/" + repoName).toString());
526
527 Repository dst = createBareRepository();
528 try (Transport t = Transport.open(dst, badRefsURI);
529 FetchConnection c = t.openFetch()) {
530
531
532 badRefsRepo.startFailing();
533
534 badRefsRepo.getRefDatabase().refresh();
535 c.fetch(NullProgressMonitor.INSTANCE,
536 Collections.singleton(c.getRef(master)),
537 Collections.<ObjectId> emptySet());
538 fail("Successfully served ref with value " + c.getRef(master));
539 } catch (TransportException err) {
540 assertEquals("internal server error", err.getMessage());
541 }
542 } finally {
543 noRefServer.tearDown();
544 }
545 }
546
547 @Test
548 public void testPush_NotAuthorized() throws Exception {
549 final TestRepository src = createTestRepository();
550 final RevBlob Q_txt = src.blob("new text");
551 final RevCommit Q = src.commit().add("Q", Q_txt).create();
552 final Repository db = src.getRepository();
553 final String dstName = Constants.R_HEADS + "new.branch";
554
555
556
557 try (Transport t = Transport.open(db, remoteURI)) {
558 final String srcExpr = Q.name();
559 final boolean forceUpdate = false;
560 final String localName = null;
561 final ObjectId oldId = null;
562
563 RemoteRefUpdate u = new RemoteRefUpdate(src.getRepository(),
564 srcExpr, dstName, forceUpdate, localName, oldId);
565 try {
566 t.push(NullProgressMonitor.INSTANCE, Collections.singleton(u));
567 fail("anonymous push incorrectly accepted without error");
568 } catch (TransportException e) {
569 final String exp = remoteURI + ": "
570 + JGitText.get().authenticationNotSupported;
571 assertEquals(exp, e.getMessage());
572 }
573 }
574
575 List<AccessEvent> requests = getRequests();
576 assertEquals(1, requests.size());
577
578 AccessEvent info = requests.get(0);
579 assertEquals("GET", info.getMethod());
580 assertEquals(join(remoteURI, "info/refs"), info.getPath());
581 assertEquals(1, info.getParameters().size());
582 assertEquals("git-receive-pack", info.getParameter("service"));
583 assertEquals(401, info.getStatus());
584 }
585
586 @Test
587 public void testPush_CreateBranch() throws Exception {
588 final TestRepository src = createTestRepository();
589 final RevBlob Q_txt = src.blob("new text");
590 final RevCommit Q = src.commit().add("Q", Q_txt).create();
591 final Repository db = src.getRepository();
592 final String dstName = Constants.R_HEADS + "new.branch";
593
594 enableReceivePack();
595
596 try (Transport t = Transport.open(db, remoteURI)) {
597 final String srcExpr = Q.name();
598 final boolean forceUpdate = false;
599 final String localName = null;
600 final ObjectId oldId = null;
601
602 RemoteRefUpdate u = new RemoteRefUpdate(src.getRepository(),
603 srcExpr, dstName, forceUpdate, localName, oldId);
604 t.push(NullProgressMonitor.INSTANCE, Collections.singleton(u));
605 }
606
607 assertTrue(remoteRepository.hasObject(Q_txt));
608 assertNotNull("has " + dstName, remoteRepository.exactRef(dstName));
609 assertEquals(Q, remoteRepository.exactRef(dstName).getObjectId());
610 fsck(remoteRepository, Q);
611
612 final ReflogReader log = remoteRepository.getReflogReader(dstName);
613 assertNotNull("has log for " + dstName, log);
614
615 final ReflogEntry last = log.getLastEntry();
616 assertNotNull("has last entry", last);
617 assertEquals(ObjectId.zeroId(), last.getOldId());
618 assertEquals(Q, last.getNewId());
619 assertEquals("anonymous", last.getWho().getName());
620
621
622
623
624
625 final String clientHost = remoteURI.getHost();
626 assertEquals("anonymous@" + clientHost, last.getWho().getEmailAddress());
627 assertEquals("push: created", last.getComment());
628
629 List<AccessEvent> requests = getRequests();
630 assertEquals(2, requests.size());
631
632 AccessEvent info = requests.get(0);
633 assertEquals("GET", info.getMethod());
634 assertEquals(join(remoteURI, "info/refs"), info.getPath());
635 assertEquals(1, info.getParameters().size());
636 assertEquals("git-receive-pack", info.getParameter("service"));
637 assertEquals(200, info.getStatus());
638 assertEquals("application/x-git-receive-pack-advertisement", info
639 .getResponseHeader(HDR_CONTENT_TYPE));
640
641 AccessEvent service = requests.get(1);
642 assertEquals("POST", service.getMethod());
643 assertEquals(join(remoteURI, "git-receive-pack"), service.getPath());
644 assertEquals(0, service.getParameters().size());
645 assertNotNull("has content-length", service
646 .getRequestHeader(HDR_CONTENT_LENGTH));
647 assertNull("not chunked", service
648 .getRequestHeader(HDR_TRANSFER_ENCODING));
649
650 assertEquals(200, service.getStatus());
651 assertEquals("application/x-git-receive-pack-result", service
652 .getResponseHeader(HDR_CONTENT_TYPE));
653 }
654
655 @Test
656 public void testPush_ChunkedEncoding() throws Exception {
657 final TestRepository<Repository> src = createTestRepository();
658 final RevBlob Q_bin = src.blob(new TestRng("Q").nextBytes(128 * 1024));
659 final RevCommit Q = src.commit().add("Q", Q_bin).create();
660 final Repository db = src.getRepository();
661 final String dstName = Constants.R_HEADS + "new.branch";
662
663 enableReceivePack();
664
665 final StoredConfig cfg = db.getConfig();
666 cfg.setInt("core", null, "compression", 0);
667 cfg.setInt("http", null, "postbuffer", 8 * 1024);
668 cfg.save();
669
670 try (Transport t = Transport.open(db, remoteURI)) {
671 final String srcExpr = Q.name();
672 final boolean forceUpdate = false;
673 final String localName = null;
674 final ObjectId oldId = null;
675
676 RemoteRefUpdate u = new RemoteRefUpdate(src.getRepository(),
677 srcExpr, dstName, forceUpdate, localName, oldId);
678 t.push(NullProgressMonitor.INSTANCE, Collections.singleton(u));
679 }
680
681 assertTrue(remoteRepository.hasObject(Q_bin));
682 assertNotNull("has " + dstName, remoteRepository.exactRef(dstName));
683 assertEquals(Q, remoteRepository.exactRef(dstName).getObjectId());
684 fsck(remoteRepository, Q);
685
686 List<AccessEvent> requests = getRequests();
687 assertEquals(2, requests.size());
688
689 AccessEvent info = requests.get(0);
690 assertEquals("GET", info.getMethod());
691 assertEquals(join(remoteURI, "info/refs"), info.getPath());
692 assertEquals(1, info.getParameters().size());
693 assertEquals("git-receive-pack", info.getParameter("service"));
694 assertEquals(200, info.getStatus());
695 assertEquals("application/x-git-receive-pack-advertisement", info
696 .getResponseHeader(HDR_CONTENT_TYPE));
697
698 AccessEvent service = requests.get(1);
699 assertEquals("POST", service.getMethod());
700 assertEquals(join(remoteURI, "git-receive-pack"), service.getPath());
701 assertEquals(0, service.getParameters().size());
702 assertNull("no content-length", service
703 .getRequestHeader(HDR_CONTENT_LENGTH));
704 assertEquals("chunked", service.getRequestHeader(HDR_TRANSFER_ENCODING));
705
706 assertEquals(200, service.getStatus());
707 assertEquals("application/x-git-receive-pack-result", service
708 .getResponseHeader(HDR_CONTENT_TYPE));
709 }
710
711 private void enableReceivePack() throws IOException {
712 final StoredConfig cfg = remoteRepository.getConfig();
713 cfg.setBoolean("http", null, "receivepack", true);
714 cfg.save();
715 }
716
717 private final class TestRepoResolver
718 implements RepositoryResolver<HttpServletRequest> {
719
720 private final TestRepository<Repository> repo;
721
722 private final String repoName;
723
724 private TestRepoResolver(TestRepository<Repository> repo,
725 String repoName) {
726 this.repo = repo;
727 this.repoName = repoName;
728 }
729
730 public Repository open(HttpServletRequest req, String name)
731 throws RepositoryNotFoundException, ServiceNotEnabledException {
732 if (!name.equals(repoName))
733 throw new RepositoryNotFoundException(name);
734
735 Repository db = repo.getRepository();
736 db.incrementOpen();
737 return db;
738 }
739 }
740 }