}
/*
- * Invokes UploadPack with protocol v2 and sends it the given lines,
+ * Invokes UploadPack with specified protocol version and sends it the given lines,
* and returns UploadPack's output stream.
*/
- private ByteArrayInputStream uploadPackV2Setup(
+ private ByteArrayInputStream uploadPackSetup(String version,
Consumer<UploadPack> postConstructionSetup, String... inputLines)
throws Exception {
ByteArrayInputStream send = linesAsInputStream(inputLines);
- server.getConfig().setString("protocol", null, "version", "2");
+ server.getConfig().setString("protocol", null, "version", version);
UploadPack up = new UploadPack(server);
if (postConstructionSetup != null) {
postConstructionSetup.accept(up);
}
- up.setExtraParameters(Sets.of("version=2"));
+ up.setExtraParameters(Sets.of("version=".concat(version)));
ByteArrayOutputStream recv = new ByteArrayOutputStream();
up.upload(send, recv, null);
}
}
+ /*
+ * Invokes UploadPack with protocol v1 and sends it the given lines.
+ * Returns UploadPack's output stream, not including the capability
+ * advertisement by the server.
+ */
+ private ByteArrayInputStream uploadPackV1(
+ Consumer<UploadPack> postConstructionSetup,
+ String... inputLines)
+ throws Exception {
+ ByteArrayInputStream recvStream =
+ uploadPackSetup("1", postConstructionSetup, inputLines);
+ PacketLineIn pckIn = new PacketLineIn(recvStream);
+
+ // drain capabilities
+ while (!PacketLineIn.isEnd(pckIn.readString())) {
+ // do nothing
+ }
+ return recvStream;
+ }
+
+ private ByteArrayInputStream uploadPackV1(String... inputLines) throws Exception {
+ return uploadPackV1(null, inputLines);
+ }
+
/*
* Invokes UploadPack with protocol v2 and sends it the given lines.
* Returns UploadPack's output stream, not including the capability
String... inputLines)
throws Exception {
ByteArrayInputStream recvStream =
- uploadPackV2Setup(postConstructionSetup, inputLines);
+ uploadPackSetup("2", postConstructionSetup, inputLines);
PacketLineIn pckIn = new PacketLineIn(recvStream);
// drain capabilities
@Test
public void testV2Capabilities() throws Exception {
TestV2Hook hook = new TestV2Hook();
- ByteArrayInputStream recvStream = uploadPackV2Setup(
+ ByteArrayInputStream recvStream = uploadPackSetup( "2",
(UploadPack up) -> {up.setProtocolV2Hook(hook);},
PacketLineIn.end());
PacketLineIn pckIn = new PacketLineIn(recvStream);
String fetchCapability) throws Exception {
server.getConfig().setBoolean(configSection, null, configName, true);
ByteArrayInputStream recvStream =
- uploadPackV2Setup(null, PacketLineIn.end());
+ uploadPackSetup("2", null, PacketLineIn.end());
PacketLineIn pckIn = new PacketLineIn(recvStream);
assertThat(pckIn.readString(), is("version 2"));
String configName, String fetchCapability) throws Exception {
server.getConfig().setBoolean(configSection, null, configName, false);
ByteArrayInputStream recvStream =
- uploadPackV2Setup(null, PacketLineIn.end());
+ uploadPackSetup("2", null, PacketLineIn.end());
PacketLineIn pckIn = new PacketLineIn(recvStream);
assertThat(pckIn.readString(), is("version 2"));
server.getConfig().setBoolean("uploadpack", null, "allowrefinwant", true);
server.getConfig().setBoolean("uploadpack", null, "advertiserefinwant", false);
ByteArrayInputStream recvStream =
- uploadPackV2Setup(null, PacketLineIn.end());
+ uploadPackSetup("2", null, PacketLineIn.end());
PacketLineIn pckIn = new PacketLineIn(recvStream);
assertThat(pckIn.readString(), is("version 2"));
PacketLineIn.end() };
TestV2Hook testHook = new TestV2Hook();
- uploadPackV2Setup((UploadPack up) -> {up.setProtocolV2Hook(testHook);}, lines);
+ uploadPackSetup("2", (UploadPack up) -> {up.setProtocolV2Hook(testHook);}, lines);
LsRefsV2Request req = testHook.lsRefsRequest;
assertEquals(2, req.getServerOptions().size());
PacketLineIn.end() };
TestV2Hook testHook = new TestV2Hook();
- uploadPackV2Setup((UploadPack up) -> {up.setProtocolV2Hook(testHook);}, lines);
+ uploadPackSetup("2", (UploadPack up) -> {up.setProtocolV2Hook(testHook);}, lines);
FetchV2Request req = testHook.fetchRequest;
assertNotNull(req);
assertEquals(1, ((RefCallsCountingRepository)server).numRefCalls());
}
+ @Test
+ public void testNotAdvertisedWantsV1Fetch() throws Exception {
+ String commonInBlob = "abcdefghijklmnopqrstuvwxyz";
+
+ RevBlob parentBlob = remote.blob(commonInBlob + "a");
+ RevCommit parent = remote
+ .commit(remote.tree(remote.file("foo", parentBlob)));
+ RevBlob childBlob = remote.blob(commonInBlob + "b");
+ RevCommit child = remote
+ .commit(remote.tree(remote.file("foo", childBlob)), parent);
+ remote.update("branch1", child);
+
+ uploadPackV1("want " + child.toObjectId().getName() + "\n",
+ PacketLineIn.end(),
+ "have " + parent.toObjectId().getName() + "\n",
+ "done\n", PacketLineIn.end());
+
+ assertEquals(0, stats.getNotAdvertisedWants());
+ }
+
+ @Test
+ public void testNotAdvertisedWantsV1FetchRequestPolicyReachableCommit() throws Exception {
+ String commonInBlob = "abcdefghijklmnopqrstuvwxyz";
+
+ RevBlob parentBlob = remote.blob(commonInBlob + "a");
+ RevCommit parent = remote
+ .commit(remote.tree(remote.file("foo", parentBlob)));
+ RevBlob childBlob = remote.blob(commonInBlob + "b");
+ RevCommit child = remote
+ .commit(remote.tree(remote.file("foo", childBlob)), parent);
+
+ remote.update("branch1", child);
+
+ uploadPackV1((UploadPack up) -> {up.setRequestPolicy(RequestPolicy.REACHABLE_COMMIT);},
+ "want " + parent.toObjectId().getName() + "\n",
+ PacketLineIn.end(),
+ "done\n", PacketLineIn.end());
+
+ assertEquals(1, stats.getNotAdvertisedWants());
+ }
+
+ @Test
+ public void testNotAdvertisedWantsV2FetchThinPack() throws Exception {
+ String commonInBlob = "abcdefghijklmnopqrstuvwxyz";
+
+ RevBlob parentBlob = remote.blob(commonInBlob + "a");
+ RevCommit parent = remote
+ .commit(remote.tree(remote.file("foo", parentBlob)));
+ RevBlob childBlob = remote.blob(commonInBlob + "b");
+ RevCommit child = remote
+ .commit(remote.tree(remote.file("foo", childBlob)), parent);
+ remote.update("branch1", child);
+
+ ByteArrayInputStream recvStream = uploadPackV2("command=fetch\n",
+ PacketLineIn.delimiter(),
+ "want " + child.toObjectId().getName() + "\n",
+ "have " + parent.toObjectId().getName() + "\n", "thin-pack\n",
+ "done\n", PacketLineIn.end());
+ PacketLineIn pckIn = new PacketLineIn(recvStream);
+
+ assertThat(pckIn.readString(), is("packfile"));
+
+ assertEquals(0, stats.getNotAdvertisedWants());
+ }
+
+ @Test
+ public void testNotAdvertisedWantsV2FetchRequestPolicyReachableCommit() throws Exception {
+ String commonInBlob = "abcdefghijklmnopqrstuvwxyz";
+
+ RevBlob parentBlob = remote.blob(commonInBlob + "a");
+ RevCommit parent = remote
+ .commit(remote.tree(remote.file("foo", parentBlob)));
+ RevBlob childBlob = remote.blob(commonInBlob + "b");
+ RevCommit child = remote
+ .commit(remote.tree(remote.file("foo", childBlob)), parent);
+
+ remote.update("branch1", child);
+
+ uploadPackV2((UploadPack up) -> {up.setRequestPolicy(RequestPolicy.REACHABLE_COMMIT);},
+ "command=fetch\n",
+ PacketLineIn.delimiter(),
+ "want " + parent.toObjectId().getName() + "\n", "thin-pack\n",
+ "done\n", PacketLineIn.end());
+
+ assertEquals(1, stats.getNotAdvertisedWants());
+ }
+
private class RefCallsCountingRepository extends InMemoryRepository {
private final InMemoryRepository.MemRefDatabase refdb;
private int numRefCalls;
if (req.wasDoneReceived()) {
processHaveLines(req.getPeerHas(), ObjectId.zeroId(),
- new PacketLineOut(NullOutputStream.INSTANCE));
+ new PacketLineOut(NullOutputStream.INSTANCE),
+ accumulator);
} else {
pckOut.writeString("acknowledgments\n"); //$NON-NLS-1$
for (ObjectId id : req.getPeerHas()) {
}
}
processHaveLines(req.getPeerHas(), ObjectId.zeroId(),
- new PacketLineOut(NullOutputStream.INSTANCE));
+ new PacketLineOut(NullOutputStream.INSTANCE),
+ accumulator);
if (okToGiveUp()) {
pckOut.writeString("ready\n"); //$NON-NLS-1$
} else if (commonBase.isEmpty()) {
}
if (PacketLineIn.isEnd(line)) {
- last = processHaveLines(peerHas, last, pckOut);
+ last = processHaveLines(peerHas, last, pckOut, accumulator);
if (commonBase.isEmpty() || multiAck != MultiAck.OFF)
pckOut.writeString("NAK\n"); //$NON-NLS-1$
if (noDone && sentReady) {
peerHas.add(ObjectId.fromString(line.substring(5)));
accumulator.haves++;
} else if (line.equals("done")) { //$NON-NLS-1$
- last = processHaveLines(peerHas, last, pckOut);
+ last = processHaveLines(peerHas, last, pckOut, accumulator);
if (commonBase.isEmpty())
pckOut.writeString("NAK\n"); //$NON-NLS-1$
}
}
- private ObjectId processHaveLines(List<ObjectId> peerHas, ObjectId last, PacketLineOut out)
+ private ObjectId processHaveLines(List<ObjectId> peerHas, ObjectId last,
+ PacketLineOut out, PackStatistics.Accumulator accumulator)
throws IOException {
preUploadHook.onBeginNegotiateRound(this, wantIds, peerHas.size());
if (wantAll.isEmpty() && !wantIds.isEmpty())
- parseWants();
+ parseWants(accumulator);
if (peerHas.isEmpty())
return last;
return last;
}
- private void parseWants() throws IOException {
+ private void parseWants(PackStatistics.Accumulator accumulator) throws IOException {
List<ObjectId> notAdvertisedWants = null;
for (ObjectId obj : wantIds) {
if (!advertised.contains(obj)) {
notAdvertisedWants.add(obj);
}
}
- if (notAdvertisedWants != null)
+ if (notAdvertisedWants != null) {
+ accumulator.notAdvertisedWants = notAdvertisedWants.size();
+
+ long startReachabilityChecking = System.currentTimeMillis();
+
requestValidator.checkWants(this, notAdvertisedWants);
+ accumulator.reachabilityCheckDuration = System.currentTimeMillis() -
+ startReachabilityChecking;
+ }
+
AsyncRevObjectQueue q = walk.parseAny(wantIds, true);
try {
RevObject obj;