diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java index a6fc63359..cf13582db 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java @@ -193,6 +193,13 @@ public abstract class BasePackFetchConnection extends BasePackConnection */ public static final String OPTION_ALLOW_TIP_SHA1_IN_WANT = GitProtocolConstants.OPTION_ALLOW_TIP_SHA1_IN_WANT; + /** + * The client supports fetching objects that are reachable from a tip of a + * ref that is allowed to fetch. + * @since 4.1 + */ + public static final String OPTION_ALLOW_REACHABLE_SHA1_IN_WANT = GitProtocolConstants.OPTION_ALLOW_REACHABLE_SHA1_IN_WANT; + private final RevWalk walk; /** All commits that are immediately reachable by a local ref. */ 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 8d2d554b9..efde06262 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/GitProtocolConstants.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/GitProtocolConstants.java @@ -129,6 +129,14 @@ public class GitProtocolConstants { */ public static final String OPTION_ALLOW_TIP_SHA1_IN_WANT = "allow-tip-sha1-in-want"; //$NON-NLS-1$ + /** + * The client supports fetching objects that are reachable from a tip of a + * ref that is allowed to fetch. + * + * @since 4.1 + */ + public static final String OPTION_ALLOW_REACHABLE_SHA1_IN_WANT = "allow-reachable-sha1-in-want"; //$NON-NLS-1$ + /** * Symbolic reference support for better negotiation. * 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 138002e63..f4de82147 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransferConfig.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransferConfig.java @@ -71,6 +71,7 @@ public class TransferConfig { private final boolean safeForWindows; private final boolean safeForMacOS; private final boolean allowTipSha1InWant; + private final boolean allowReachableSha1InWant; private final String[] hideRefs; TransferConfig(final Repository db) { @@ -94,6 +95,8 @@ public class TransferConfig { allowTipSha1InWant = rc.getBoolean( "uploadpack", "allowtipsha1inwant", false); //$NON-NLS-1$ //$NON-NLS-2$ + allowReachableSha1InWant = rc.getBoolean( + "uploadpack", "allowreachablesha1inwant", false); //$NON-NLS-1$ //$NON-NLS-2$ hideRefs = rc.getStringList("uploadpack", null, "hiderefs"); //$NON-NLS-1$ //$NON-NLS-2$ } @@ -120,6 +123,14 @@ public class TransferConfig { return allowTipSha1InWant; } + /** + * @return allow clients to request non-tip SHA-1s? + * @since 4.1 + */ + public boolean isAllowReachableSha1InWant() { + return allowReachableSha1InWant; + } + /** * @return {@link RefFilter} respecting configured hidden refs. * @since 3.1 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 753277dd3..1e6aabbe0 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java @@ -46,6 +46,7 @@ package org.eclipse.jgit.transport; import static org.eclipse.jgit.lib.RefDatabase.ALL; import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_AGENT; import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_ALLOW_TIP_SHA1_IN_WANT; +import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_ALLOW_REACHABLE_SHA1_IN_WANT; import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_INCLUDE_TAG; import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_MULTI_ACK; import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_MULTI_ACK_DETAILED; @@ -552,8 +553,13 @@ public class UploadPack { */ public void setTransferConfig(TransferConfig tc) { this.transferConfig = tc != null ? tc : new TransferConfig(db); - setRequestPolicy(transferConfig.isAllowTipSha1InWant() - ? RequestPolicy.TIP : RequestPolicy.ADVERTISED); + if (transferConfig.isAllowTipSha1InWant()) { + setRequestPolicy(transferConfig.isAllowReachableSha1InWant() + ? RequestPolicy.REACHABLE_COMMIT_TIP : RequestPolicy.TIP); + } else { + setRequestPolicy(transferConfig.isAllowReachableSha1InWant() + ? RequestPolicy.REACHABLE_COMMIT : RequestPolicy.ADVERTISED); + } } /** @return the configured logger. */ @@ -808,6 +814,10 @@ public class UploadPack { || policy == RequestPolicy.REACHABLE_COMMIT_TIP || policy == null) adv.advertiseCapability(OPTION_ALLOW_TIP_SHA1_IN_WANT); + if (policy == RequestPolicy.REACHABLE_COMMIT + || policy == RequestPolicy.REACHABLE_COMMIT_TIP + || policy == null) + adv.advertiseCapability(OPTION_ALLOW_REACHABLE_SHA1_IN_WANT); adv.advertiseCapability(OPTION_AGENT, UserAgent.get()); adv.setDerefTags(true); Map advertisedOrDefaultRefs = getAdvertisedOrDefaultRefs();