diff options
Diffstat (limited to 'org.eclipse.jgit')
10 files changed, 195 insertions, 3 deletions
diff --git a/org.eclipse.jgit/.settings/.api_filters b/org.eclipse.jgit/.settings/.api_filters index 14c505de01..83a83817f4 100644 --- a/org.eclipse.jgit/.settings/.api_filters +++ b/org.eclipse.jgit/.settings/.api_filters @@ -8,6 +8,14 @@ </message_arguments> </filter> </resource> + <resource path="src/org/eclipse/jgit/transport/ProtocolV2Hook.java" type="org.eclipse.jgit.transport.ProtocolV2Hook"> + <filter id="404000815"> + <message_arguments> + <message_argument value="org.eclipse.jgit.transport.ProtocolV2Hook"/> + <message_argument value="onObjectInfo(ObjectInfoRequest)"/> + </message_arguments> + </filter> + </resource> <resource path="src/org/eclipse/jgit/transport/SshConstants.java" type="org.eclipse.jgit.transport.SshConstants"> <filter id="1142947843"> <message_arguments> diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/CloneCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/CloneCommand.java index cf7bc1f263..3aa711455b 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CloneCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CloneCommand.java @@ -173,7 +173,11 @@ public class CloneCommand extends TransportCommand<CloneCommand, Git> { Repository repository = init(); FetchResult fetchResult = null; Thread cleanupHook = new Thread(() -> cleanup()); - Runtime.getRuntime().addShutdownHook(cleanupHook); + try { + Runtime.getRuntime().addShutdownHook(cleanupHook); + } catch (IllegalStateException e) { + // ignore - the VM is already shutting down + } try { fetchResult = fetch(repository, u); } catch (IOException ioe) { @@ -197,7 +201,11 @@ public class CloneCommand extends TransportCommand<CloneCommand, Git> { cleanup(); throw e; } finally { - Runtime.getRuntime().removeShutdownHook(cleanupHook); + try { + Runtime.getRuntime().removeShutdownHook(cleanupHook); + } catch (IllegalStateException e) { + // ignore - the VM is already shutting down + } } if (!noCheckout) { try { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java index 5d5ba12baa..d5b3643af9 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java @@ -527,10 +527,12 @@ public class RevWalk implements Iterable<RevCommit>, AutoCloseable { private List<Ref> getMergedInto(RevCommit needle, Collection<Ref> haystacks, Enum returnStrategy, ProgressMonitor monitor) throws IOException { List<Ref> result = new ArrayList<>(); + List<RevCommit> uninteresting = new ArrayList<>(); RevFilter oldRF = filter; TreeFilter oldTF = treeFilter; try { finishDelayedFreeFlags(); + reset(~freeFlags & APP_FLAGS); filter = RevFilter.ALL; treeFilter = TreeFilter.ALL; for (Ref r: haystacks) { @@ -559,13 +561,14 @@ public class RevWalk implements Iterable<RevCommit>, AutoCloseable { } if(!commitFound){ markUninteresting(c); + uninteresting.add(c); if (returnStrategy == GetMergedIntoStrategy.RETURN_ON_FIRST_NOT_FOUND) { return result; } } } } finally { - reset(~freeFlags & APP_FLAGS); + roots.addAll(uninteresting); filter = oldRF; treeFilter = oldTF; } 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)); } |