aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/UploadPackTest.java47
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/GitProtocolConstants.java7
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/ObjectInfoRequest.java69
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/ProtocolV2Hook.java12
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/ProtocolV2HookChain.java8
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/ProtocolV2Parser.java35
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/TransferConfig.java11
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java31
8 files changed, 220 insertions, 0 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 b0b5f68efa..f4bbb4c9f8 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
@@ -460,6 +460,8 @@ public class UploadPackTest {
private FetchV2Request fetchRequest;
+ private ObjectInfoRequest objectInfoRequest;
+
@Override
public void onCapabilities(CapabilitiesV2Request req) {
capabilitiesRequest = req;
@@ -474,6 +476,11 @@ public class UploadPackTest {
public void onFetch(FetchV2Request req) {
fetchRequest = req;
}
+
+ @Override
+ public void onObjectInfo(ObjectInfoRequest req) {
+ objectInfoRequest = req;
+ }
}
@Test
@@ -2641,4 +2648,44 @@ public class UploadPackTest {
return refdb;
}
}
+
+ @Test
+ public void testObjectInfo() throws Exception {
+ server.getConfig().setBoolean("uploadpack", null, "advertiseobjectinfo",
+ true);
+
+ RevBlob blob1 = remote.blob("foobar");
+ RevBlob blob2 = remote.blob("fooba");
+ RevTree tree = remote.tree(remote.file("1", blob1),
+ remote.file("2", blob2));
+ RevCommit commit = remote.commit(tree);
+ remote.update("master", commit);
+
+ TestV2Hook hook = new TestV2Hook();
+ ByteArrayInputStream recvStream = uploadPackV2((UploadPack up) -> {
+ up.setProtocolV2Hook(hook);
+ }, "command=object-info\n", "size",
+ "oid " + ObjectId.toString(blob1.getId()),
+ "oid " + ObjectId.toString(blob2.getId()), PacketLineIn.end());
+ PacketLineIn pckIn = new PacketLineIn(recvStream);
+
+ assertThat(hook.objectInfoRequest, notNullValue());
+ assertThat(pckIn.readString(), is("size"));
+ assertThat(pckIn.readString(),
+ is(ObjectId.toString(blob1.getId()) + " 6"));
+ assertThat(pckIn.readString(),
+ is(ObjectId.toString(blob2.getId()) + " 5"));
+ assertTrue(PacketLineIn.isEnd(pckIn.readString()));
+ }
+
+ @Test
+ public void testObjectInfo_invalidOid() throws Exception {
+ server.getConfig().setBoolean("uploadpack", null, "advertiseobjectinfo",
+ true);
+
+ assertThrows(UploadPackInternalServerErrorException.class,
+ () -> uploadPackV2("command=object-info\n", "size",
+ "oid invalid",
+ PacketLineIn.end()));
+ }
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/GitProtocolConstants.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/GitProtocolConstants.java
index c5e52bef98..aaa9308ac3 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/GitProtocolConstants.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/GitProtocolConstants.java
@@ -255,6 +255,13 @@ public final class GitProtocolConstants {
public static final String COMMAND_FETCH = "fetch"; //$NON-NLS-1$
/**
+ * The server supports the object-info capability.
+ *
+ * @since 5.13
+ */
+ public static final String COMMAND_OBJECT_INFO = "object-info"; //$NON-NLS-1$
+
+ /**
* HTTP header to set by clients to request a specific git protocol version
* in the HTTP transport.
*
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ObjectInfoRequest.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ObjectInfoRequest.java
new file mode 100644
index 0000000000..86a2716675
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ObjectInfoRequest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2021, Google LLC. and others
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.transport;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.jgit.lib.ObjectId;
+
+/**
+ * object-info request.
+ *
+ * <p>
+ * This is the parsed request for an object-info call, used as input to
+ * {@link ProtocolV2Hook}.
+ *
+ * @see <a href=
+ * "https://www.kernel.org/pub/software/scm/git/docs/technical/protocol-v2.html#_object_info">object-info
+ * documentation</a>
+ *
+ * @since 5.13
+ */
+public final class ObjectInfoRequest {
+ private final List<ObjectId> objectIDs;
+
+ private ObjectInfoRequest(List<ObjectId> objectIDs) {
+ this.objectIDs = objectIDs;
+ }
+
+ /** @return object IDs that the client requested. */
+ public List<ObjectId> getObjectIDs() {
+ return this.objectIDs;
+ }
+
+ /** @return A builder of {@link ObjectInfoRequest}. */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /** A builder for {@link ObjectInfoRequest}. */
+ public static final class Builder {
+ private List<ObjectId> objectIDs = Collections.emptyList();
+
+ private Builder() {
+ }
+
+ /**
+ * @param value
+ * @return the Builder
+ */
+ public Builder setObjectIDs(List<ObjectId> value) {
+ objectIDs = value;
+ return this;
+ }
+
+ /** @return ObjectInfoRequest */
+ public ObjectInfoRequest build() {
+ return new ObjectInfoRequest(
+ Collections.unmodifiableList(objectIDs));
+ }
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ProtocolV2Hook.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ProtocolV2Hook.java
index bfa7490665..d7626df3fa 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ProtocolV2Hook.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ProtocolV2Hook.java
@@ -55,4 +55,16 @@ public interface ProtocolV2Hook {
throws ServiceMayNotContinueException {
// Do nothing by default
}
+
+ /**
+ * @param req
+ * the object-info request
+ * @throws ServiceMayNotContinueException
+ * abort; the message will be sent to the user
+ * @since 5.13
+ */
+ default void onObjectInfo(ObjectInfoRequest req)
+ throws ServiceMayNotContinueException {
+ // Do nothing by default
+ }
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ProtocolV2HookChain.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ProtocolV2HookChain.java
index 4cf8db6f5e..7b3a4cea06 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ProtocolV2HookChain.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ProtocolV2HookChain.java
@@ -71,6 +71,14 @@ public class ProtocolV2HookChain implements ProtocolV2Hook {
}
}
+ @Override
+ public void onObjectInfo(ObjectInfoRequest req)
+ throws ServiceMayNotContinueException {
+ for (ProtocolV2Hook hook : hooks) {
+ hook.onObjectInfo(req);
+ }
+ }
+
private ProtocolV2HookChain(List<? extends ProtocolV2Hook> hooks) {
this.hooks = Collections.unmodifiableList(hooks);
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ProtocolV2Parser.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ProtocolV2Parser.java
index 92f0133f5a..6cec4b9a3f 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ProtocolV2Parser.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ProtocolV2Parser.java
@@ -28,6 +28,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
+import org.eclipse.jgit.errors.InvalidObjectIdException;
import org.eclipse.jgit.errors.PackProtocolException;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.ObjectId;
@@ -248,4 +249,38 @@ final class ProtocolV2Parser {
return builder.setRefPrefixes(prefixes).build();
}
+ ObjectInfoRequest parseObjectInfoRequest(PacketLineIn pckIn)
+ throws PackProtocolException, IOException {
+ ObjectInfoRequest.Builder builder = ObjectInfoRequest.builder();
+ List<ObjectId> objectIDs = new ArrayList<>();
+
+ String line = pckIn.readString();
+
+ if (PacketLineIn.isEnd(line)) {
+ return builder.build();
+ }
+
+ if (!line.equals("size")) { //$NON-NLS-1$
+ throw new PackProtocolException(MessageFormat
+ .format(JGitText.get().unexpectedPacketLine, line));
+ }
+
+ for (String line2 : pckIn.readStrings()) {
+ if (!line2.startsWith("oid ")) { //$NON-NLS-1$
+ throw new PackProtocolException(MessageFormat
+ .format(JGitText.get().unexpectedPacketLine, line2));
+ }
+
+ String oidStr = line2.substring("oid ".length()); //$NON-NLS-1$
+
+ try {
+ objectIDs.add(ObjectId.fromString(oidStr));
+ } catch (InvalidObjectIdException e) {
+ throw new PackProtocolException(MessageFormat
+ .format(JGitText.get().invalidObject, oidStr), e);
+ }
+ }
+
+ return builder.setObjectIDs(objectIDs).build();
+ }
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransferConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransferConfig.java
index da97f1e580..02be434887 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransferConfig.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransferConfig.java
@@ -123,6 +123,7 @@ public class TransferConfig {
private final boolean advertiseSidebandAll;
private final boolean advertiseWaitForDone;
+ private final boolean advertiseObjectInfo;
final @Nullable ProtocolVersion protocolVersion;
final String[] hideRefs;
@@ -211,6 +212,8 @@ public class TransferConfig {
"advertisesidebandall", false);
advertiseWaitForDone = rc.getBoolean("uploadpack",
"advertisewaitfordone", false);
+ advertiseObjectInfo = rc.getBoolean("uploadpack",
+ "advertiseobjectinfo", false);
}
/**
@@ -318,6 +321,14 @@ public class TransferConfig {
}
/**
+ * @return true to advertise object-info to all clients
+ * @since 5.13
+ */
+ public boolean isAdvertiseObjectInfo() {
+ return advertiseObjectInfo;
+ }
+
+ /**
* Get {@link org.eclipse.jgit.transport.RefFilter} respecting configured
* hidden 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 37a1c1e589..07b348d0e7 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java
@@ -17,6 +17,7 @@ import static org.eclipse.jgit.transport.GitProtocolConstants.CAPABILITY_REF_IN_
import static org.eclipse.jgit.transport.GitProtocolConstants.CAPABILITY_SERVER_OPTION;
import static org.eclipse.jgit.transport.GitProtocolConstants.COMMAND_FETCH;
import static org.eclipse.jgit.transport.GitProtocolConstants.COMMAND_LS_REFS;
+import static org.eclipse.jgit.transport.GitProtocolConstants.COMMAND_OBJECT_INFO;
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_AGENT;
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_ALLOW_REACHABLE_SHA1_IN_WANT;
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_ALLOW_TIP_SHA1_IN_WANT;
@@ -1269,6 +1270,32 @@ public class UploadPack {
}
}
+ private void objectInfo(PacketLineOut pckOut) throws IOException {
+ ProtocolV2Parser parser = new ProtocolV2Parser(transferConfig);
+ ObjectInfoRequest req = parser.parseObjectInfoRequest(pckIn);
+
+ protocolV2Hook.onObjectInfo(req);
+
+ ObjectReader or = getRepository().newObjectReader();
+
+ // Size is the only attribute currently supported.
+ pckOut.writeString("size"); //$NON-NLS-1$
+
+ for (ObjectId oid : req.getObjectIDs()) {
+ long size;
+ try {
+ size = or.getObjectSize(oid, ObjectReader.OBJ_ANY);
+ } catch (MissingObjectException e) {
+ throw new PackProtocolException(MessageFormat
+ .format(JGitText.get().missingObject, oid.name()), e);
+ }
+
+ pckOut.writeString(oid.getName() + " " + size); //$NON-NLS-1$
+ }
+
+ pckOut.end();
+ }
+
/*
* Returns true if this is the last command and we should tear down the
* connection.
@@ -1295,6 +1322,10 @@ public class UploadPack {
fetchV2(pckOut);
return false;
}
+ if (command.equals("command=" + COMMAND_OBJECT_INFO)) { //$NON-NLS-1$
+ objectInfo(pckOut);
+ return false;
+ }
throw new PackProtocolException(MessageFormat
.format(JGitText.get().unknownTransportCommand, command));
}