Teach UploadPack "filter" in protocol v2 fetch
If the configuration variable uploadpack.allowfilter is true, advertise
that "filter" is supported, and support it if the client sends such an
argument.
Change-Id: I7de66c0a0ada46ff71c5ba124d4ffa7c47254c3b
Signed-off-by: Jonathan Tan <jonathantanmy@google.com>
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/UploadPackTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/UploadPackTest.java
index d1a3172..ef083da 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/UploadPackTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/UploadPackTest.java
@@ -410,6 +410,22 @@
}
@Test
+ public void testV2CapabilitiesAllowFilter() throws Exception {
+ server.getConfig().setBoolean("uploadpack", null, "allowfilter", true);
+ ByteArrayInputStream recvStream =
+ uploadPackV2Setup(null, null, PacketLineIn.END);
+ PacketLineIn pckIn = new PacketLineIn(recvStream);
+
+ assertThat(pckIn.readString(), is("version 2"));
+ assertThat(
+ Arrays.asList(pckIn.readString(), pckIn.readString()),
+ // TODO(jonathantanmy) This check overspecifies the
+ // order of the capabilities of "fetch".
+ hasItems("ls-refs", "fetch=filter shallow"));
+ assertTrue(pckIn.readString() == PacketLineIn.END);
+ }
+
+ @Test
@SuppressWarnings("boxing")
public void testV2EmptyRequest() throws Exception {
ByteArrayInputStream recvStream = uploadPackV2(PacketLineIn.END);
@@ -1018,6 +1034,50 @@
PacketLineIn.END);
}
+ @Test
+ public void testV2FetchFilter() throws Exception {
+ RevBlob big = remote.blob("foobar");
+ RevBlob small = remote.blob("fooba");
+ RevTree tree = remote.tree(remote.file("1", big),
+ remote.file("2", small));
+ RevCommit commit = remote.commit(tree);
+ remote.update("master", commit);
+
+ server.getConfig().setBoolean("uploadpack", null, "allowfilter", true);
+
+ ByteArrayInputStream recvStream = uploadPackV2(
+ "command=fetch\n",
+ PacketLineIn.DELIM,
+ "want " + commit.toObjectId().getName() + "\n",
+ "filter blob:limit=5\n",
+ "done\n",
+ PacketLineIn.END);
+ PacketLineIn pckIn = new PacketLineIn(recvStream);
+ assertThat(pckIn.readString(), is("packfile"));
+ parsePack(recvStream);
+
+ assertFalse(client.hasObject(big.toObjectId()));
+ assertTrue(client.hasObject(small.toObjectId()));
+ }
+
+ @Test
+ public void testV2FetchFilterWhenNotAllowed() throws Exception {
+ RevCommit commit = remote.commit().message("0").create();
+ remote.update("master", commit);
+
+ server.getConfig().setBoolean("uploadpack", null, "allowfilter", false);
+
+ thrown.expect(PackProtocolException.class);
+ thrown.expectMessage("unexpected filter blob:limit=5");
+ uploadPackV2(
+ "command=fetch\n",
+ PacketLineIn.DELIM,
+ "want " + commit.toObjectId().getName() + "\n",
+ "filter blob:limit=5\n",
+ "done\n",
+ PacketLineIn.END);
+ }
+
private static class RejectAllRefFilter implements RefFilter {
@Override
public Map<String, Ref> filter(Map<String, Ref> refs) {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java
index ea6bd3a..f70ead9 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java
@@ -958,6 +958,7 @@
}
boolean includeTag = false;
+ boolean filterReceived = false;
while ((line = pckIn.readString()) != PacketLineIn.END) {
if (line.startsWith("want ")) { //$NON-NLS-1$
wantIds.add(ObjectId.fromString(line.substring(5)));
@@ -1014,6 +1015,13 @@
throw new PackProtocolException(
JGitText.get().deepenSinceWithDeepen);
}
+ } else if (transferConfig.isAllowFilter()
+ && line.startsWith(OPTION_FILTER + ' ')) {
+ if (filterReceived) {
+ throw new PackProtocolException(JGitText.get().tooManyFilters);
+ }
+ filterReceived = true;
+ parseFilter(line.substring(OPTION_FILTER.length() + 1));
} else {
throw new PackProtocolException(MessageFormat
.format(JGitText.get().unexpectedPacketLine, line));
@@ -1113,7 +1121,10 @@
ArrayList<String> caps = new ArrayList<>();
caps.add("version 2"); //$NON-NLS-1$
caps.add(COMMAND_LS_REFS);
- caps.add(COMMAND_FETCH + '=' + OPTION_SHALLOW);
+ caps.add(
+ COMMAND_FETCH + '=' +
+ (transferConfig.isAllowFilter() ? OPTION_FILTER + ' ' : "") + //$NON-NLS-1$
+ OPTION_SHALLOW);
return caps;
}