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 d1a31720b..ef083da18 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 @@ -409,6 +409,22 @@ public class UploadPackTest { assertTrue(pckIn.readString() == PacketLineIn.END); } + @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 { @@ -1018,6 +1034,50 @@ public class UploadPackTest { 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 filter(Map 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 ea6bd3a91..f70ead929 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 @@ public class UploadPack { } 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 @@ public class UploadPack { 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 @@ public class UploadPack { ArrayList 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; }