@Test
  public void testInitialClone_Packed() throws Exception {
    new TestRepository<Repository>(remoteRepository).packAndPrune();

    Repository dst = createBareRepository();
    assertFalse(dst.hasObject(A_txt));

    Transport t = Transport.open(dst, remoteURI);
    ((TransportHttp) t).setUseSmartHttp(false);
    try {
      t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
    } finally {
      t.close();
    }

    assertTrue(dst.hasObject(A_txt));
    assertEquals(B, dst.getRef(master).getObjectId());
    fsck(dst, B);

    List<AccessEvent> req;

    req = getRequests(loose(remoteURI, B));
    assertEquals(1, req.size());
    assertEquals("GET", req.get(0).getMethod());
    assertEquals(0, req.get(0).getParameters().size());
    assertEquals(404, req.get(0).getStatus());

    req = getRequests(join(remoteURI, "objects/info/packs"));
    assertEquals(1, req.size());
    assertEquals("GET", req.get(0).getMethod());
    assertEquals(0, req.get(0).getParameters().size());
    assertEquals(200, req.get(0).getStatus());
    assertEquals("text/plain;charset=UTF-8", req.get(0).getResponseHeader(HDR_CONTENT_TYPE));
  }
  @Test
  public void testInitialClone_Small() throws Exception {
    Repository dst = createBareRepository();
    assertFalse(dst.hasObject(A_txt));

    Transport t = Transport.open(dst, remoteURI);
    ((TransportHttp) t).setUseSmartHttp(false);
    try {
      t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
    } finally {
      t.close();
    }

    assertTrue(dst.hasObject(A_txt));
    assertEquals(B, dst.getRef(master).getObjectId());
    fsck(dst, B);

    List<AccessEvent> loose = getRequests(loose(remoteURI, A_txt));
    assertEquals(1, loose.size());
    assertEquals("GET", loose.get(0).getMethod());
    assertEquals(0, loose.get(0).getParameters().size());
    assertEquals(200, loose.get(0).getStatus());
    assertEquals(
        "application/x-git-loose-object", loose.get(0).getResponseHeader(HDR_CONTENT_TYPE));
  }
  private void checkConnectivity() throws IOException {
    ObjectIdSubclassMap<ObjectId> baseObjects = null;
    ObjectIdSubclassMap<ObjectId> providedObjects = null;

    if (checkReferencedIsReachable) {
      baseObjects = parser.getBaseObjectIds();
      providedObjects = parser.getNewObjectIds();
    }
    parser = null;

    final ObjectWalk ow = new ObjectWalk(db);
    ow.setRetainBody(false);
    if (checkReferencedIsReachable) {
      ow.sort(RevSort.TOPO);
      if (!baseObjects.isEmpty()) ow.sort(RevSort.BOUNDARY, true);
    }

    for (final ReceiveCommand cmd : commands) {
      if (cmd.getResult() != Result.NOT_ATTEMPTED) continue;
      if (cmd.getType() == ReceiveCommand.Type.DELETE) continue;
      ow.markStart(ow.parseAny(cmd.getNewId()));
    }
    for (final ObjectId have : advertisedHaves) {
      RevObject o = ow.parseAny(have);
      ow.markUninteresting(o);

      if (checkReferencedIsReachable && !baseObjects.isEmpty()) {
        o = ow.peel(o);
        if (o instanceof RevCommit) o = ((RevCommit) o).getTree();
        if (o instanceof RevTree) ow.markUninteresting(o);
      }
    }

    RevCommit c;
    while ((c = ow.next()) != null) {
      if (checkReferencedIsReachable //
          && !c.has(RevFlag.UNINTERESTING) //
          && !providedObjects.contains(c))
        throw new MissingObjectException(c, Constants.TYPE_COMMIT);
    }

    RevObject o;
    while ((o = ow.nextObject()) != null) {
      if (o.has(RevFlag.UNINTERESTING)) continue;

      if (checkReferencedIsReachable) {
        if (providedObjects.contains(o)) continue;
        else throw new MissingObjectException(o, o.getType());
      }

      if (o instanceof RevBlob && !db.hasObject(o))
        throw new MissingObjectException(o, Constants.TYPE_BLOB);
    }

    if (checkReferencedIsReachable) {
      for (ObjectId id : baseObjects) {
        o = ow.parseAny(id);
        if (!o.has(RevFlag.UNINTERESTING)) throw new MissingObjectException(o, o.getType());
      }
    }
  }
  @Test
  public void testSuccess() throws Exception {
    // Manually force a delta of an object so we reuse it later.
    //
    TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(1024);

    packHeader(pack, 2);
    pack.write((Constants.OBJ_BLOB) << 4 | 1);
    deflate(pack, new byte[] {'a'});

    pack.write((Constants.OBJ_REF_DELTA) << 4 | 4);
    a.copyRawTo(pack);
    deflate(pack, new byte[] {0x1, 0x1, 0x1, 'b'});

    digest(pack);
    openPack(pack);

    // Verify the only storage of b is our packed delta above.
    //
    ObjectDirectory od = (ObjectDirectory) src.getObjectDatabase();
    assertTrue("has b", src.hasObject(b));
    assertFalse("b not loose", od.fileFor(b).exists());

    // Now use b but in a different commit than what is hidden.
    //
    TestRepository<Repository> s = new TestRepository<Repository>(src);
    RevCommit N = s.commit().parent(B).add("q", b).create();
    s.update(R_MASTER, N);

    // Push this new content to the remote, doing strict validation.
    //
    TransportLocal t =
        new TransportLocal(src, uriOf(dst), dst.getDirectory()) {
          @Override
          ReceivePack createReceivePack(final Repository db) {
            db.close();
            dst.incrementOpen();

            final ReceivePack rp = super.createReceivePack(dst);
            rp.setCheckReceivedObjects(true);
            rp.setCheckReferencedObjectsAreReachable(true);
            rp.setAdvertiseRefsHook(new HidePrivateHook());
            return rp;
          }
        };
    RemoteRefUpdate u =
        new RemoteRefUpdate( //
            src, //
            R_MASTER, // src name
            R_MASTER, // dst name
            false, // do not force update
            null, // local tracking branch
            null // expected id
            );
    PushResult r;
    try {
      t.setPushThin(true);
      r = t.push(PM, Collections.singleton(u));
    } finally {
      t.close();
    }

    assertNotNull("have result", r);
    assertNull("private not advertised", r.getAdvertisedRef(R_PRIVATE));
    assertSame("master updated", RemoteRefUpdate.Status.OK, u.getStatus());
    assertEquals(N, dst.resolve(R_MASTER));
  }