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.transport;
45
46 import static org.junit.Assert.assertEquals;
47 import static org.junit.Assert.assertFalse;
48 import static org.junit.Assert.assertNotNull;
49 import static org.junit.Assert.assertNull;
50 import static org.junit.Assert.assertSame;
51 import static org.junit.Assert.assertTrue;
52 import static org.junit.Assert.fail;
53
54 import java.io.ByteArrayInputStream;
55 import java.io.IOException;
56 import java.net.URISyntaxException;
57 import java.security.MessageDigest;
58 import java.util.Collections;
59 import java.util.HashMap;
60 import java.util.Map;
61 import java.util.Set;
62 import java.util.concurrent.atomic.AtomicReference;
63 import java.util.zip.Deflater;
64
65 import org.eclipse.jgit.errors.MissingObjectException;
66 import org.eclipse.jgit.errors.UnpackException;
67 import org.eclipse.jgit.internal.storage.file.ObjectDirectory;
68 import org.eclipse.jgit.internal.storage.pack.BinaryDelta;
69 import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase;
70 import org.eclipse.jgit.junit.TestRepository;
71 import org.eclipse.jgit.lib.Constants;
72 import org.eclipse.jgit.lib.NullProgressMonitor;
73 import org.eclipse.jgit.lib.ObjectId;
74 import org.eclipse.jgit.lib.ObjectInserter;
75 import org.eclipse.jgit.lib.ObjectLoader;
76 import org.eclipse.jgit.lib.Ref;
77 import org.eclipse.jgit.lib.Repository;
78 import org.eclipse.jgit.revwalk.RevBlob;
79 import org.eclipse.jgit.revwalk.RevCommit;
80 import org.eclipse.jgit.revwalk.RevTree;
81 import org.eclipse.jgit.revwalk.RevWalk;
82 import org.eclipse.jgit.util.NB;
83 import org.eclipse.jgit.util.TemporaryBuffer;
84 import org.junit.After;
85 import org.junit.Before;
86 import org.junit.Test;
87
88 public class ReceivePackAdvertiseRefsHookTest extends LocalDiskRepositoryTestCase {
89 private static final NullProgressMonitor PM = NullProgressMonitor.INSTANCE;
90
91 private static final String R_MASTER = Constants.R_HEADS + Constants.MASTER;
92
93 private static final String R_PRIVATE = Constants.R_HEADS + "private";
94
95 private Repository src;
96
97 private Repository dst;
98
99 private RevCommit A, B, P;
100
101 private RevBlob a, b;
102
103 @Override
104 @Before
105 public void setUp() throws Exception {
106 super.setUp();
107
108 src = createBareRepository();
109 dst = createBareRepository();
110
111
112
113 TestRepository<Repository> d = new TestRepository<>(dst);
114 a = d.blob("a");
115 A = d.commit(d.tree(d.file("a", a)));
116 B = d.commit().parent(A).create();
117 d.update(R_MASTER, B);
118
119
120
121 try (Transport t = Transport.open(src, uriOf(dst))) {
122 t.fetch(PM, Collections.singleton(new RefSpec("+refs/*:refs/*")));
123 assertEquals(B, src.resolve(R_MASTER));
124 }
125
126
127
128 b = d.blob("b");
129 P = d.commit(d.tree(d.file("b", b)), A);
130 d.update(R_PRIVATE, P);
131 }
132
133 @Test
134 public void testFilterHidesPrivate() throws Exception {
135 Map<String, Ref> refs;
136 try (TransportLocal t = new TransportLocal(src, uriOf(dst),
137 dst.getDirectory()) {
138 @Override
139 ReceivePack createReceivePack(Repository db) {
140 db.close();
141 dst.incrementOpen();
142
143 final ReceivePack rp = super.createReceivePack(dst);
144 rp.setAdvertiseRefsHook(new HidePrivateHook());
145 return rp;
146 }
147 }) {
148 try (PushConnection c = t.openPush()) {
149 refs = c.getRefsMap();
150 }
151 }
152
153 assertNotNull(refs);
154 assertNull("no private", refs.get(R_PRIVATE));
155 assertNull("no HEAD", refs.get(Constants.HEAD));
156 assertEquals(1, refs.size());
157
158 Ref master = refs.get(R_MASTER);
159 assertNotNull("has master", master);
160 assertEquals(B, master.getObjectId());
161 }
162
163 @Test
164 public void resetsHaves() throws Exception {
165 AtomicReference<Set<ObjectId>> haves = new AtomicReference<>();
166 try (TransportLocal t = new TransportLocal(src, uriOf(dst),
167 dst.getDirectory()) {
168 @Override
169 ReceivePack createReceivePack(Repository db) {
170 dst.incrementOpen();
171
172 ReceivePack rp = super.createReceivePack(dst);
173 rp.setAdvertiseRefsHook(new AdvertiseRefsHook() {
174 @Override
175 public void advertiseRefs(BaseReceivePack rp2)
176 throws ServiceMayNotContinueException {
177 rp.setAdvertisedRefs(rp.getRepository().getAllRefs(),
178 null);
179 new HidePrivateHook().advertiseRefs(rp);
180 haves.set(rp.getAdvertisedObjects());
181 }
182
183 @Override
184 public void advertiseRefs(UploadPack uploadPack)
185 throws ServiceMayNotContinueException {
186 throw new UnsupportedOperationException();
187 }
188 });
189 return rp;
190 }
191 }) {
192 try (PushConnection c = t.openPush()) {
193
194 }
195 }
196
197 assertEquals(1, haves.get().size());
198 assertTrue(haves.get().contains(B));
199 assertFalse(haves.get().contains(P));
200 }
201
202 private TransportLocal newTransportLocalWithStrictValidation()
203 throws Exception {
204 return new TransportLocal(src, uriOf(dst), dst.getDirectory()) {
205 @Override
206 ReceivePack createReceivePack(Repository db) {
207 db.close();
208 dst.incrementOpen();
209
210 final ReceivePack rp = super.createReceivePack(dst);
211 rp.setCheckReceivedObjects(true);
212 rp.setCheckReferencedObjectsAreReachable(true);
213 rp.setAdvertiseRefsHook(new HidePrivateHook());
214 return rp;
215 }
216 };
217 }
218
219 @Test
220 public void testSuccess() throws Exception {
221
222
223 TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(1024);
224
225 packHeader(pack, 2);
226 pack.write((Constants.OBJ_BLOB) << 4 | 1);
227 deflate(pack, new byte[] { 'a' });
228
229 pack.write((Constants.OBJ_REF_DELTA) << 4 | 4);
230 a.copyRawTo(pack);
231 deflate(pack, new byte[] { 0x1, 0x1, 0x1, 'b' });
232
233 digest(pack);
234 openPack(pack);
235
236
237
238 ObjectDirectory od = (ObjectDirectory) src.getObjectDatabase();
239 assertTrue("has b", src.hasObject(b));
240 assertFalse("b not loose", od.fileFor(b).exists());
241
242
243
244 TestRepository<Repository> s = new TestRepository<>(src);
245 RevCommit N = s.commit().parent(B).add("q", b).create();
246 s.update(R_MASTER, N);
247
248
249
250 PushResult r;
251 RemoteRefUpdate u = new RemoteRefUpdate(
252 src,
253 R_MASTER,
254 R_MASTER,
255 false,
256 null,
257 null
258 );
259 try (TransportLocal t = newTransportLocalWithStrictValidation()) {
260 t.setPushThin(true);
261 r = t.push(PM, Collections.singleton(u));
262 dst.close();
263 }
264
265 assertNotNull("have result", r);
266 assertNull("private not advertised", r.getAdvertisedRef(R_PRIVATE));
267 assertSame("master updated", RemoteRefUpdate.Status.OK, u.getStatus());
268 assertEquals(N, dst.resolve(R_MASTER));
269 }
270
271 @Test
272 public void testCreateBranchAtHiddenCommitFails() throws Exception {
273 final TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(64);
274 packHeader(pack, 0);
275 digest(pack);
276
277 final TemporaryBuffer.Heap inBuf = new TemporaryBuffer.Heap(256);
278 final PacketLineOut inPckLine = new PacketLineOut(inBuf);
279 inPckLine.writeString(ObjectId.zeroId().name() + ' ' + P.name() + ' '
280 + "refs/heads/s" + '\0'
281 + BasePackPushConnection.CAPABILITY_REPORT_STATUS);
282 inPckLine.end();
283 pack.writeTo(inBuf, PM);
284
285 final TemporaryBuffer.Heap outBuf = new TemporaryBuffer.Heap(1024);
286 final ReceivePack rp = new ReceivePack(dst);
287 rp.setCheckReceivedObjects(true);
288 rp.setCheckReferencedObjectsAreReachable(true);
289 rp.setAdvertiseRefsHook(new HidePrivateHook());
290 try {
291 receive(rp, inBuf, outBuf);
292 fail("Expected UnpackException");
293 } catch (UnpackException failed) {
294 Throwable err = failed.getCause();
295 assertTrue(err instanceof MissingObjectException);
296 MissingObjectException moe = (MissingObjectException) err;
297 assertEquals(P, moe.getObjectId());
298 }
299
300 final PacketLineIn r = asPacketLineIn(outBuf);
301 String master = r.readString();
302 int nul = master.indexOf('\0');
303 assertTrue("has capability list", nul > 0);
304 assertEquals(B.name() + ' ' + R_MASTER, master.substring(0, nul));
305 assertSame(PacketLineIn.END, r.readString());
306
307 assertEquals("unpack error Missing commit " + P.name(), r.readString());
308 assertEquals("ng refs/heads/s n/a (unpacker error)", r.readString());
309 assertSame(PacketLineIn.END, r.readString());
310 }
311
312 private static void receive(final ReceivePack rp,
313 final TemporaryBuffer.Heap inBuf, final TemporaryBuffer.Heap outBuf)
314 throws IOException {
315 rp.receive(new ByteArrayInputStream(inBuf.toByteArray()), outBuf, null);
316 }
317
318 @Test
319 public void testUsingHiddenDeltaBaseFails() throws Exception {
320 byte[] delta = { 0x1, 0x1, 0x1, 'c' };
321 TestRepository<Repository> s = new TestRepository<>(src);
322 RevCommit N = s.commit().parent(B).add("q",
323 s.blob(BinaryDelta.apply(dst.open(b).getCachedBytes(), delta)))
324 .create();
325
326 final TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(1024);
327 packHeader(pack, 3);
328 copy(pack, src.open(N));
329 copy(pack, src.open(s.parseBody(N).getTree()));
330 pack.write((Constants.OBJ_REF_DELTA) << 4 | 4);
331 b.copyRawTo(pack);
332 deflate(pack, delta);
333 digest(pack);
334
335 final TemporaryBuffer.Heap inBuf = new TemporaryBuffer.Heap(1024);
336 final PacketLineOut inPckLine = new PacketLineOut(inBuf);
337 inPckLine.writeString(ObjectId.zeroId().name() + ' ' + N.name() + ' '
338 + "refs/heads/s" + '\0'
339 + BasePackPushConnection.CAPABILITY_REPORT_STATUS);
340 inPckLine.end();
341 pack.writeTo(inBuf, PM);
342
343 final TemporaryBuffer.Heap outBuf = new TemporaryBuffer.Heap(1024);
344 final ReceivePack rp = new ReceivePack(dst);
345 rp.setCheckReceivedObjects(true);
346 rp.setCheckReferencedObjectsAreReachable(true);
347 rp.setAdvertiseRefsHook(new HidePrivateHook());
348 try {
349 receive(rp, inBuf, outBuf);
350 fail("Expected UnpackException");
351 } catch (UnpackException failed) {
352 Throwable err = failed.getCause();
353 assertTrue(err instanceof MissingObjectException);
354 MissingObjectException moe = (MissingObjectException) err;
355 assertEquals(b, moe.getObjectId());
356 }
357
358 final PacketLineIn r = asPacketLineIn(outBuf);
359 String master = r.readString();
360 int nul = master.indexOf('\0');
361 assertTrue("has capability list", nul > 0);
362 assertEquals(B.name() + ' ' + R_MASTER, master.substring(0, nul));
363 assertSame(PacketLineIn.END, r.readString());
364
365 assertEquals("unpack error Missing blob " + b.name(), r.readString());
366 assertEquals("ng refs/heads/s n/a (unpacker error)", r.readString());
367 assertSame(PacketLineIn.END, r.readString());
368 }
369
370 @Test
371 public void testUsingHiddenCommonBlobFails() throws Exception {
372
373
374 TestRepository<Repository> s = new TestRepository<>(src);
375 RevCommit N = s.commit().parent(B).add("q", s.blob("b")).create();
376
377
378
379 final TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(1024);
380 packHeader(pack, 2);
381 copy(pack, src.open(N));
382 copy(pack,src.open(s.parseBody(N).getTree()));
383 digest(pack);
384
385 final TemporaryBuffer.Heap inBuf = new TemporaryBuffer.Heap(1024);
386 final PacketLineOut inPckLine = new PacketLineOut(inBuf);
387 inPckLine.writeString(ObjectId.zeroId().name() + ' ' + N.name() + ' '
388 + "refs/heads/s" + '\0'
389 + BasePackPushConnection.CAPABILITY_REPORT_STATUS);
390 inPckLine.end();
391 pack.writeTo(inBuf, PM);
392
393 final TemporaryBuffer.Heap outBuf = new TemporaryBuffer.Heap(1024);
394 final ReceivePack rp = new ReceivePack(dst);
395 rp.setCheckReceivedObjects(true);
396 rp.setCheckReferencedObjectsAreReachable(true);
397 rp.setAdvertiseRefsHook(new HidePrivateHook());
398 try {
399 receive(rp, inBuf, outBuf);
400 fail("Expected UnpackException");
401 } catch (UnpackException failed) {
402 Throwable err = failed.getCause();
403 assertTrue(err instanceof MissingObjectException);
404 MissingObjectException moe = (MissingObjectException) err;
405 assertEquals(b, moe.getObjectId());
406 }
407
408 final PacketLineIn r = asPacketLineIn(outBuf);
409 String master = r.readString();
410 int nul = master.indexOf('\0');
411 assertTrue("has capability list", nul > 0);
412 assertEquals(B.name() + ' ' + R_MASTER, master.substring(0, nul));
413 assertSame(PacketLineIn.END, r.readString());
414
415 assertEquals("unpack error Missing blob " + b.name(), r.readString());
416 assertEquals("ng refs/heads/s n/a (unpacker error)", r.readString());
417 assertSame(PacketLineIn.END, r.readString());
418 }
419
420 @Test
421 public void testUsingUnknownBlobFails() throws Exception {
422
423
424 TestRepository<Repository> s = new TestRepository<>(src);
425 RevBlob n = s.blob("n");
426 RevCommit N = s.commit().parent(B).add("q", n).create();
427
428
429
430 final TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(1024);
431 packHeader(pack, 2);
432 copy(pack, src.open(N));
433 copy(pack,src.open(s.parseBody(N).getTree()));
434 digest(pack);
435
436 final TemporaryBuffer.Heap inBuf = new TemporaryBuffer.Heap(1024);
437 final PacketLineOut inPckLine = new PacketLineOut(inBuf);
438 inPckLine.writeString(ObjectId.zeroId().name() + ' ' + N.name() + ' '
439 + "refs/heads/s" + '\0'
440 + BasePackPushConnection.CAPABILITY_REPORT_STATUS);
441 inPckLine.end();
442 pack.writeTo(inBuf, PM);
443
444 final TemporaryBuffer.Heap outBuf = new TemporaryBuffer.Heap(1024);
445 final ReceivePack rp = new ReceivePack(dst);
446 rp.setCheckReceivedObjects(true);
447 rp.setCheckReferencedObjectsAreReachable(true);
448 rp.setAdvertiseRefsHook(new HidePrivateHook());
449 try {
450 receive(rp, inBuf, outBuf);
451 fail("Expected UnpackException");
452 } catch (UnpackException failed) {
453 Throwable err = failed.getCause();
454 assertTrue(err instanceof MissingObjectException);
455 MissingObjectException moe = (MissingObjectException) err;
456 assertEquals(n, moe.getObjectId());
457 }
458
459 final PacketLineIn r = asPacketLineIn(outBuf);
460 String master = r.readString();
461 int nul = master.indexOf('\0');
462 assertTrue("has capability list", nul > 0);
463 assertEquals(B.name() + ' ' + R_MASTER, master.substring(0, nul));
464 assertSame(PacketLineIn.END, r.readString());
465
466 assertEquals("unpack error Missing blob " + n.name(), r.readString());
467 assertEquals("ng refs/heads/s n/a (unpacker error)", r.readString());
468 assertSame(PacketLineIn.END, r.readString());
469 }
470
471 @Test
472 public void testIncludesInvalidGitmodules() throws Exception {
473 final TemporaryBuffer.Heap inBuf = setupSourceRepoInvalidGitmodules();
474 final TemporaryBuffer.Heap outBuf = new TemporaryBuffer.Heap(1024);
475 final ReceivePack rp = new ReceivePack(dst);
476 rp.setCheckReceivedObjects(true);
477 rp.setCheckReferencedObjectsAreReachable(true);
478 rp.setAdvertiseRefsHook(new HidePrivateHook());
479 try {
480 receive(rp, inBuf, outBuf);
481 fail("Expected UnpackException");
482 } catch (UnpackException failed) {
483 Throwable err = failed.getCause();
484 assertTrue(err instanceof IOException);
485 }
486
487 final PacketLineIn r = asPacketLineIn(outBuf);
488 String master = r.readString();
489 int nul = master.indexOf('\0');
490 assertTrue("has capability list", nul > 0);
491 assertEquals(B.name() + ' ' + R_MASTER, master.substring(0, nul));
492 assertSame(PacketLineIn.END, r.readString());
493
494 String errorLine = r.readString();
495 System.out.println(errorLine);
496 assertTrue(errorLine.startsWith(
497 "unpack error Invalid submodule URL '-"));
498 assertEquals("ng refs/heads/s n/a (unpacker error)", r.readString());
499 assertSame(PacketLineIn.END, r.readString());
500 }
501
502 private TemporaryBuffer.Heap setupSourceRepoInvalidGitmodules()
503 throws IOException, Exception, MissingObjectException {
504 String fakeGitmodules = new StringBuilder()
505 .append("[submodule \"test\"]\n")
506 .append(" path = xlib\n")
507 .append(" url = https://example.com/repo/xlib.git\n\n")
508 .append("[submodule \"test2\"]\n")
509 .append(" path = zlib\n")
510 .append(" url = -upayload.sh\n")
511 .toString();
512
513 TestRepository<Repository> s = new TestRepository<>(src);
514 RevBlob blob = s.blob(fakeGitmodules);
515 RevCommit N = s.commit().parent(B)
516 .add(".gitmodules", blob).create();
517 RevTree t = s.parseBody(N).getTree();
518
519 final TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(1024);
520 packHeader(pack, 3);
521 copy(pack, src.open(N));
522 copy(pack, src.open(t));
523 copy(pack, src.open(blob));
524 digest(pack);
525
526 final TemporaryBuffer.Heap inBuf = new TemporaryBuffer.Heap(1024);
527 final PacketLineOut inPckLine = new PacketLineOut(inBuf);
528 inPckLine.writeString(ObjectId.zeroId().name() + ' ' + N.name() + ' '
529 + "refs/heads/s" + '\0'
530 + BasePackPushConnection.CAPABILITY_REPORT_STATUS);
531 inPckLine.end();
532 pack.writeTo(inBuf, PM);
533 return inBuf;
534 }
535
536 @Test
537 public void testUsingUnknownTreeFails() throws Exception {
538 TestRepository<Repository> s = new TestRepository<>(src);
539 RevCommit N = s.commit().parent(B).add("q", s.blob("a")).create();
540 RevTree t = s.parseBody(N).getTree();
541
542
543
544 final TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(1024);
545 packHeader(pack, 1);
546 copy(pack, src.open(N));
547 digest(pack);
548
549 final TemporaryBuffer.Heap inBuf = new TemporaryBuffer.Heap(1024);
550 final PacketLineOut inPckLine = new PacketLineOut(inBuf);
551 inPckLine.writeString(ObjectId.zeroId().name() + ' ' + N.name() + ' '
552 + "refs/heads/s" + '\0'
553 + BasePackPushConnection.CAPABILITY_REPORT_STATUS);
554 inPckLine.end();
555 pack.writeTo(inBuf, PM);
556
557 final TemporaryBuffer.Heap outBuf = new TemporaryBuffer.Heap(1024);
558 final ReceivePack rp = new ReceivePack(dst);
559 rp.setCheckReceivedObjects(true);
560 rp.setCheckReferencedObjectsAreReachable(true);
561 rp.setAdvertiseRefsHook(new HidePrivateHook());
562 try {
563 receive(rp, inBuf, outBuf);
564 fail("Expected UnpackException");
565 } catch (UnpackException failed) {
566 Throwable err = failed.getCause();
567 assertTrue(err instanceof MissingObjectException);
568 MissingObjectException moe = (MissingObjectException) err;
569 assertEquals(t, moe.getObjectId());
570 }
571
572 final PacketLineIn r = asPacketLineIn(outBuf);
573 String master = r.readString();
574 int nul = master.indexOf('\0');
575 assertTrue("has capability list", nul > 0);
576 assertEquals(B.name() + ' ' + R_MASTER, master.substring(0, nul));
577 assertSame(PacketLineIn.END, r.readString());
578
579 assertEquals("unpack error Missing tree " + t.name(), r.readString());
580 assertEquals("ng refs/heads/s n/a (unpacker error)", r.readString());
581 assertSame(PacketLineIn.END, r.readString());
582 }
583
584 private static void packHeader(TemporaryBuffer.Heap tinyPack, int cnt)
585 throws IOException {
586 final byte[] hdr = new byte[8];
587 NB.encodeInt32(hdr, 0, 2);
588 NB.encodeInt32(hdr, 4, cnt);
589
590 tinyPack.write(Constants.PACK_SIGNATURE);
591 tinyPack.write(hdr, 0, 8);
592 }
593
594 private static void copy(TemporaryBuffer.Heap tinyPack, ObjectLoader ldr)
595 throws IOException {
596 final byte[] buf = new byte[64];
597 final byte[] content = ldr.getCachedBytes();
598 int dataLength = content.length;
599 int nextLength = dataLength >>> 4;
600 int size = 0;
601 buf[size++] = (byte) ((nextLength > 0 ? 0x80 : 0x00)
602 | (ldr.getType() << 4) | (dataLength & 0x0F));
603 dataLength = nextLength;
604 while (dataLength > 0) {
605 nextLength >>>= 7;
606 buf[size++] = (byte) ((nextLength > 0 ? 0x80 : 0x00) | (dataLength & 0x7F));
607 dataLength = nextLength;
608 }
609 tinyPack.write(buf, 0, size);
610 deflate(tinyPack, content);
611 }
612
613 private static void deflate(TemporaryBuffer.Heap tinyPack,
614 final byte[] content)
615 throws IOException {
616 final Deflater deflater = new Deflater();
617 final byte[] buf = new byte[128];
618 deflater.setInput(content, 0, content.length);
619 deflater.finish();
620 do {
621 final int n = deflater.deflate(buf, 0, buf.length);
622 if (n > 0)
623 tinyPack.write(buf, 0, n);
624 } while (!deflater.finished());
625 }
626
627 private static void digest(TemporaryBuffer.Heap buf) throws IOException {
628 MessageDigest md = Constants.newMessageDigest();
629 md.update(buf.toByteArray());
630 buf.write(md.digest());
631 }
632
633 private ObjectInserter inserter;
634
635 @After
636 public void release() {
637 if (inserter != null) {
638 inserter.close();
639 }
640 }
641
642 private void openPack(TemporaryBuffer.Heap buf) throws IOException {
643 if (inserter == null)
644 inserter = src.newObjectInserter();
645
646 final byte[] raw = buf.toByteArray();
647 PackParser p = inserter.newPackParser(new ByteArrayInputStream(raw));
648 p.setAllowThin(true);
649 p.parse(PM);
650 }
651
652 private static PacketLineIn asPacketLineIn(TemporaryBuffer.Heap buf)
653 throws IOException {
654 return new PacketLineIn(new ByteArrayInputStream(buf.toByteArray()));
655 }
656
657 private static final class HidePrivateHook extends AbstractAdvertiseRefsHook {
658 @Override
659 public Map<String, Ref> getAdvertisedRefs(Repository r, RevWalk revWalk) {
660 Map<String, Ref> refs = new HashMap<>(r.getAllRefs());
661 assertNotNull(refs.remove(R_PRIVATE));
662 return refs;
663 }
664 }
665
666 private static URIish uriOf(Repository r) throws URISyntaxException {
667 return new URIish(r.getDirectory().getAbsolutePath());
668 }
669 }