private boolean sendWants(final Collection<Ref> want) throws IOException {
    final PacketLineOut p = statelessRPC ? pckState : pckOut;
    boolean first = true;
    for (final Ref r : want) {
      try {
        if (walk.parseAny(r.getObjectId()).has(REACHABLE)) {
          // We already have this object. Asking for it is
          // not a very good idea.
          //
          continue;
        }
      } catch (IOException err) {
        // Its OK, we don't have it, but we want to fix that
        // by fetching the object from the other side.
      }

      final StringBuilder line = new StringBuilder(46);
      line.append("want ");
      line.append(r.getObjectId().name());
      if (first) {
        line.append(enableCapabilities());
        first = false;
      }
      line.append('\n');
      p.writeString(line.toString());
    }
    if (first) return false;
    p.end();
    outNeedsEnd = false;
    return true;
  }
  @Test
  public void testUsingHiddenDeltaBaseFails() throws Exception {
    byte[] delta = {0x1, 0x1, 0x1, 'c'};
    TestRepository<Repository> s = new TestRepository<Repository>(src);
    RevCommit N =
        s.commit()
            .parent(B)
            .add("q", s.blob(BinaryDelta.apply(dst.open(b).getCachedBytes(), delta)))
            .create();

    final TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(1024);
    packHeader(pack, 3);
    copy(pack, src.open(N));
    copy(pack, src.open(s.parseBody(N).getTree()));
    pack.write((Constants.OBJ_REF_DELTA) << 4 | 4);
    b.copyRawTo(pack);
    deflate(pack, delta);
    digest(pack);

    final TemporaryBuffer.Heap inBuf = new TemporaryBuffer.Heap(1024);
    final PacketLineOut inPckLine = new PacketLineOut(inBuf);
    inPckLine.writeString(
        ObjectId.zeroId().name()
            + ' '
            + N.name()
            + ' '
            + "refs/heads/s"
            + '\0'
            + BasePackPushConnection.CAPABILITY_REPORT_STATUS);
    inPckLine.end();
    pack.writeTo(inBuf, PM);

    final TemporaryBuffer.Heap outBuf = new TemporaryBuffer.Heap(1024);
    final ReceivePack rp = new ReceivePack(dst);
    rp.setCheckReceivedObjects(true);
    rp.setCheckReferencedObjectsAreReachable(true);
    rp.setAdvertiseRefsHook(new HidePrivateHook());
    try {
      receive(rp, inBuf, outBuf);
      fail("Expected UnpackException");
    } catch (UnpackException failed) {
      Throwable err = failed.getCause();
      assertTrue(err instanceof MissingObjectException);
      MissingObjectException moe = (MissingObjectException) err;
      assertEquals(b, moe.getObjectId());
    }

    final PacketLineIn r = asPacketLineIn(outBuf);
    String master = r.readString();
    int nul = master.indexOf('\0');
    assertTrue("has capability list", nul > 0);
    assertEquals(B.name() + ' ' + R_MASTER, master.substring(0, nul));
    assertSame(PacketLineIn.END, r.readString());

    assertEquals("unpack error Missing blob " + b.name(), r.readString());
    assertEquals("ng refs/heads/s n/a (unpacker error)", r.readString());
    assertSame(PacketLineIn.END, r.readString());
  }
  @Test
  public void testUsingUnknownBlobFails() throws Exception {
    // Try to use the 'n' blob that is not on the server.
    //
    TestRepository<Repository> s = new TestRepository<Repository>(src);
    RevBlob n = s.blob("n");
    RevCommit N = s.commit().parent(B).add("q", n).create();

    // But don't include it in the pack.
    //
    final TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(1024);
    packHeader(pack, 2);
    copy(pack, src.open(N));
    copy(pack, src.open(s.parseBody(N).getTree()));
    digest(pack);

    final TemporaryBuffer.Heap inBuf = new TemporaryBuffer.Heap(1024);
    final PacketLineOut inPckLine = new PacketLineOut(inBuf);
    inPckLine.writeString(
        ObjectId.zeroId().name()
            + ' '
            + N.name()
            + ' '
            + "refs/heads/s"
            + '\0'
            + BasePackPushConnection.CAPABILITY_REPORT_STATUS);
    inPckLine.end();
    pack.writeTo(inBuf, PM);

    final TemporaryBuffer.Heap outBuf = new TemporaryBuffer.Heap(1024);
    final ReceivePack rp = new ReceivePack(dst);
    rp.setCheckReceivedObjects(true);
    rp.setCheckReferencedObjectsAreReachable(true);
    rp.setAdvertiseRefsHook(new HidePrivateHook());
    try {
      receive(rp, inBuf, outBuf);
      fail("Expected UnpackException");
    } catch (UnpackException failed) {
      Throwable err = failed.getCause();
      assertTrue(err instanceof MissingObjectException);
      MissingObjectException moe = (MissingObjectException) err;
      assertEquals(n, moe.getObjectId());
    }

    final PacketLineIn r = asPacketLineIn(outBuf);
    String master = r.readString();
    int nul = master.indexOf('\0');
    assertTrue("has capability list", nul > 0);
    assertEquals(B.name() + ' ' + R_MASTER, master.substring(0, nul));
    assertSame(PacketLineIn.END, r.readString());

    assertEquals("unpack error Missing blob " + n.name(), r.readString());
    assertEquals("ng refs/heads/s n/a (unpacker error)", r.readString());
    assertSame(PacketLineIn.END, r.readString());
  }
  private void markCommon(final RevObject obj, final AckNackResult anr) throws IOException {
    if (statelessRPC && anr == AckNackResult.ACK_COMMON && !obj.has(STATE)) {
      StringBuilder s;

      s = new StringBuilder(6 + Constants.OBJECT_ID_STRING_LENGTH);
      s.append("have "); // $NON-NLS-1$
      s.append(obj.name());
      s.append('\n');
      pckState.writeString(s.toString());
      obj.add(STATE);
    }
    obj.add(COMMON);
    if (obj instanceof RevCommit) ((RevCommit) obj).carry(COMMON);
  }
  @Test
  public void testCreateBranchAtHiddenCommitFails() throws Exception {
    final TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(64);
    packHeader(pack, 0);
    digest(pack);

    final TemporaryBuffer.Heap inBuf = new TemporaryBuffer.Heap(256);
    final PacketLineOut inPckLine = new PacketLineOut(inBuf);
    inPckLine.writeString(
        ObjectId.zeroId().name()
            + ' '
            + P.name()
            + ' '
            + "refs/heads/s"
            + '\0'
            + BasePackPushConnection.CAPABILITY_REPORT_STATUS);
    inPckLine.end();
    pack.writeTo(inBuf, PM);

    final TemporaryBuffer.Heap outBuf = new TemporaryBuffer.Heap(1024);
    final ReceivePack rp = new ReceivePack(dst);
    rp.setCheckReceivedObjects(true);
    rp.setCheckReferencedObjectsAreReachable(true);
    rp.setAdvertiseRefsHook(new HidePrivateHook());
    try {
      receive(rp, inBuf, outBuf);
      fail("Expected UnpackException");
    } catch (UnpackException failed) {
      Throwable err = failed.getCause();
      assertTrue(err instanceof MissingObjectException);
      MissingObjectException moe = (MissingObjectException) err;
      assertEquals(P, moe.getObjectId());
    }

    final PacketLineIn r = asPacketLineIn(outBuf);
    String master = r.readString();
    int nul = master.indexOf('\0');
    assertTrue("has capability list", nul > 0);
    assertEquals(B.name() + ' ' + R_MASTER, master.substring(0, nul));
    assertSame(PacketLineIn.END, r.readString());

    assertEquals("unpack error Missing commit " + P.name(), r.readString());
    assertEquals("ng refs/heads/s n/a (unpacker error)", r.readString());
    assertSame(PacketLineIn.END, r.readString());
  }