From dceedbcd6e66d60f095aacfa308055b7ca6f45a7 Mon Sep 17 00:00:00 2001 From: Jonathan Nieder Date: Wed, 29 Jul 2020 20:40:50 -0700 Subject: [PATCH] Add support for tree filters when fetching Teach the FilterSpec serialization code about tree filters so they can be communicated over the wire and understood by the server. While we're here, harden the FilterSpec serialization code to throw IllegalStateException if we encounter a FilterSpec that cannot be expressed as a "filter" line. The only public API for creating a Filterspec is to pass in a "filter" line to be parsed, so these should not appear in practice. Change-Id: I9664844059ffbc9c36eb829e2d860f198b9403a0 Signed-off-by: Jonathan Nieder --- .../jgit/transport/UploadPackTest.java | 32 +++++++++++++++++++ .../eclipse/jgit/transport/FilterSpec.java | 20 +++++++----- 2 files changed, 44 insertions(+), 8 deletions(-) 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 d58e57698..bb33eefce 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 @@ -297,6 +297,38 @@ public class UploadPackTest { } } + @Test + public void testFetchWithTreeZeroFilter() throws Exception { + InMemoryRepository server2 = newRepo("server2"); + try (TestRepository remote2 = new TestRepository<>( + server2)) { + RevBlob blob1 = remote2.blob("foobar"); + RevBlob blob2 = remote2.blob("fooba"); + RevTree tree = remote2.tree(remote2.file("1", blob1), + remote2.file("2", blob2)); + RevCommit commit = remote2.commit(tree); + remote2.update("master", commit); + + server2.getConfig().setBoolean("uploadpack", null, "allowfilter", + true); + + testProtocol = new TestProtocol<>((Object req, Repository db) -> { + UploadPack up = new UploadPack(db); + return up; + }, null); + uri = testProtocol.register(ctx, server2); + + try (Transport tn = testProtocol.open(uri, client, "server2")) { + tn.setFilterSpec(FilterSpec.withTreeDepthLimit(0)); + tn.fetch(NullProgressMonitor.INSTANCE, + Collections.singletonList(new RefSpec(commit.name()))); + assertFalse(client.getObjectDatabase().has(tree.toObjectId())); + assertFalse(client.getObjectDatabase().has(blob1.toObjectId())); + assertFalse(client.getObjectDatabase().has(blob2.toObjectId())); + } + } + } + @Test public void testFetchWithNonSupportingServer() throws Exception { InMemoryRepository server2 = newRepo("server2"); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/FilterSpec.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/FilterSpec.java index d09b5579f..51e5a8f20 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/FilterSpec.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/FilterSpec.java @@ -10,6 +10,8 @@ package org.eclipse.jgit.transport; +import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_FILTER; + import java.text.MessageFormat; import org.eclipse.jgit.annotations.Nullable; @@ -146,14 +148,16 @@ public final class FilterSpec { */ @Nullable public String filterLine() { - if (blobLimit == 0) { - return GitProtocolConstants.OPTION_FILTER + " blob:none"; //$NON-NLS-1$ - } - - if (blobLimit > 0) { - return GitProtocolConstants.OPTION_FILTER + " blob:limit=" + blobLimit; //$NON-NLS-1$ + if (isNoOp()) { + return null; + } else if (blobLimit == 0 && treeDepthLimit == -1) { + return OPTION_FILTER + " blob:none"; //$NON-NLS-1$ + } else if (blobLimit > 0 && treeDepthLimit == -1) { + return OPTION_FILTER + " blob:limit=" + blobLimit; //$NON-NLS-1$ + } else if (blobLimit == -1 && treeDepthLimit >= 0) { + return OPTION_FILTER + " tree:" + treeDepthLimit; //$NON-NLS-1$ + } else { + throw new IllegalStateException(); } - - return null; } }