diff options
Diffstat (limited to 'org.eclipse.jgit/src/org/eclipse/jgit/transport')
6 files changed, 88 insertions, 18 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchV2Request.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchV2Request.java index ea639332ea..50fb9d2262 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchV2Request.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchV2Request.java @@ -36,6 +36,8 @@ public final class FetchV2Request extends FetchRequest { private final boolean doneReceived; + private final boolean waitForDone; + @NonNull private final List<String> serverOptions; @@ -50,7 +52,8 @@ public final class FetchV2Request extends FetchRequest { @NonNull Set<ObjectId> clientShallowCommits, int deepenSince, @NonNull List<String> deepenNotRefs, int depth, @NonNull FilterSpec filterSpec, - boolean doneReceived, @NonNull Set<String> clientCapabilities, + boolean doneReceived, boolean waitForDone, + @NonNull Set<String> clientCapabilities, @Nullable String agent, @NonNull List<String> serverOptions, boolean sidebandAll, @NonNull List<String> packfileUriProtocols) { super(wantIds, depth, clientShallowCommits, filterSpec, @@ -59,6 +62,7 @@ public final class FetchV2Request extends FetchRequest { this.peerHas = requireNonNull(peerHas); this.wantedRefs = requireNonNull(wantedRefs); this.doneReceived = doneReceived; + this.waitForDone = waitForDone; this.serverOptions = requireNonNull(serverOptions); this.sidebandAll = sidebandAll; this.packfileUriProtocols = packfileUriProtocols; @@ -90,7 +94,14 @@ public final class FetchV2Request extends FetchRequest { } /** - * Options received in server-option lines. The caller can choose to act on + * @return true if the request had a "wait-for-done" line + */ + boolean wasWaitForDoneReceived() { + return waitForDone; + } + + /** + * Options received in server-option lines. The caller can choose to act on * these in an application-specific way * * @return Immutable list of server options received in the request @@ -141,6 +152,8 @@ public final class FetchV2Request extends FetchRequest { boolean doneReceived; + boolean waitForDone; + @Nullable String agent; @@ -280,6 +293,16 @@ public final class FetchV2Request extends FetchRequest { } /** + * Mark that the "wait-for-done" line has been received. + * + * @return this builder + */ + Builder setWaitForDone() { + waitForDone = true; + return this; + } + + /** * Value of an agent line received after the command and before the * arguments. E.g. "agent=a.b.c/1.0" should set "a.b.c/1.0". * @@ -328,7 +351,7 @@ public final class FetchV2Request extends FetchRequest { FetchV2Request build() { return new FetchV2Request(peerHas, wantedRefs, wantIds, clientShallowCommits, deepenSince, deepenNotRefs, - depth, filterSpec, doneReceived, clientCapabilities, + depth, filterSpec, doneReceived, waitForDone, clientCapabilities, agent, Collections.unmodifiableList(serverOptions), sidebandAll, Collections.unmodifiableList(packfileUriProtocols)); 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 36fce7a3f5..c5e52bef98 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/GitProtocolConstants.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/GitProtocolConstants.java @@ -149,6 +149,13 @@ public final class GitProtocolConstants { public static final String OPTION_SIDEBAND_ALL = "sideband-all"; //$NON-NLS-1$ /** + * The server waits for client to send "done" before sending any packs back. + * + * @since 5.13 + */ + public static final String OPTION_WAIT_FOR_DONE = "wait-for-done"; //$NON-NLS-1$ + + /** * The client supports atomic pushes. If this option is used, the server * will update all refs within one atomic transaction. * 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 faccc25185..92f0133f5a 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ProtocolV2Parser.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ProtocolV2Parser.java @@ -19,6 +19,7 @@ import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SERVER_OPTI import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SIDEBAND_ALL; import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SIDE_BAND_64K; import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_THIN_PACK; +import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_WAIT_FOR_DONE; import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_WANT_REF; import java.io.IOException; @@ -123,6 +124,8 @@ final class ProtocolV2Parser { reqBuilder.addPeerHas(ObjectId.fromString(line2.substring(5))); } else if (line2.equals("done")) { //$NON-NLS-1$ reqBuilder.setDoneReceived(); + } else if (line2.equals(OPTION_WAIT_FOR_DONE)) { + reqBuilder.setWaitForDone(); } else if (line2.equals(OPTION_THIN_PACK)) { reqBuilder.addClientCapability(OPTION_THIN_PACK); } else if (line2.equals(OPTION_NO_PROGRESS)) { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/SshConstants.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/SshConstants.java index be55cd1b81..5cd5b334ab 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/SshConstants.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/SshConstants.java @@ -118,7 +118,7 @@ public final class SshConstants { * Key in an ssh config file; defines signature algorithms for public key * authentication as a comma-separated list. * - * @since 5.11 + * @since 5.11.1 */ public static final String PUBKEY_ACCEPTED_ALGORITHMS = "PubkeyAcceptedAlgorithms"; 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 83ffd4123a..da97f1e580 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransferConfig.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransferConfig.java @@ -120,7 +120,10 @@ public class TransferConfig { private final boolean allowReachableSha1InWant; private final boolean allowFilter; private final boolean allowSidebandAll; + private final boolean advertiseSidebandAll; + private final boolean advertiseWaitForDone; + final @Nullable ProtocolVersion protocolVersion; final String[] hideRefs; @@ -206,6 +209,8 @@ public class TransferConfig { "uploadpack", "allowsidebandall", false); advertiseSidebandAll = rc.getBoolean("uploadpack", "advertisesidebandall", false); + advertiseWaitForDone = rc.getBoolean("uploadpack", + "advertisewaitfordone", false); } /** @@ -305,6 +310,14 @@ public class TransferConfig { } /** + * @return true to advertise wait-for-done all to the clients + * @since 5.13 + */ + public boolean isAdvertiseWaitForDone() { + return advertiseWaitForDone; + } + + /** * 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 7f1ddaab2e..ecf1751932 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java @@ -33,6 +33,7 @@ import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SIDEBAND_AL import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SIDE_BAND; import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SIDE_BAND_64K; import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_THIN_PACK; +import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_WAIT_FOR_DONE; import static org.eclipse.jgit.transport.GitProtocolConstants.VERSION_2_REQUEST; import static org.eclipse.jgit.util.RefMap.toRefMap; @@ -1192,9 +1193,10 @@ public class UploadPack { walk.assumeShallow(req.getClientShallowCommits()); if (req.wasDoneReceived()) { - processHaveLines(req.getPeerHas(), ObjectId.zeroId(), + processHaveLines( + req.getPeerHas(), ObjectId.zeroId(), new PacketLineOut(NullOutputStream.INSTANCE, false), - accumulator); + accumulator, req.wasWaitForDoneReceived() ? Option.WAIT_FOR_DONE : Option.NONE); } else { pckOut.writeString( GitProtocolConstants.SECTION_ACKNOWLEDGMENTS + '\n'); @@ -1205,8 +1207,8 @@ public class UploadPack { } processHaveLines(req.getPeerHas(), ObjectId.zeroId(), new PacketLineOut(NullOutputStream.INSTANCE, false), - accumulator); - if (okToGiveUp()) { + accumulator, Option.NONE); + if (!req.wasWaitForDoneReceived() && okToGiveUp()) { pckOut.writeString("ready\n"); //$NON-NLS-1$ } else if (commonBase.isEmpty()) { pckOut.writeString("NAK\n"); //$NON-NLS-1$ @@ -1214,7 +1216,7 @@ public class UploadPack { sectionSent = true; } - if (req.wasDoneReceived() || okToGiveUp()) { + if (req.wasDoneReceived() || (!req.wasWaitForDoneReceived() && okToGiveUp())) { if (mayHaveShallow) { if (sectionSent) pckOut.writeDelim(); @@ -1312,6 +1314,9 @@ public class UploadPack { ? OPTION_SIDEBAND_ALL + ' ' : "") + (cachedPackUriProvider != null ? "packfile-uris " : "") + + (transferConfig.isAdvertiseWaitForDone() + ? OPTION_WAIT_FOR_DONE + ' ' + : "") + OPTION_SHALLOW); caps.add(CAPABILITY_SERVER_OPTION); return caps; @@ -1656,7 +1661,7 @@ public class UploadPack { } if (PacketLineIn.isEnd(line)) { - last = processHaveLines(peerHas, last, pckOut, accumulator); + last = processHaveLines(peerHas, last, pckOut, accumulator, Option.NONE); if (commonBase.isEmpty() || multiAck != MultiAck.OFF) pckOut.writeString("NAK\n"); //$NON-NLS-1$ if (noDone && sentReady) { @@ -1671,7 +1676,7 @@ public class UploadPack { peerHas.add(ObjectId.fromString(line.substring(5))); accumulator.haves++; } else if (line.equals("done")) { //$NON-NLS-1$ - last = processHaveLines(peerHas, last, pckOut, accumulator); + last = processHaveLines(peerHas, last, pckOut, accumulator, Option.NONE); if (commonBase.isEmpty()) pckOut.writeString("NAK\n"); //$NON-NLS-1$ @@ -1687,8 +1692,14 @@ public class UploadPack { } } + private enum Option { + WAIT_FOR_DONE, + NONE; + } + private ObjectId processHaveLines(List<ObjectId> peerHas, ObjectId last, - PacketLineOut out, PackStatistics.Accumulator accumulator) + PacketLineOut out, PackStatistics.Accumulator accumulator, + Option option) throws IOException { preUploadHook.onBeginNegotiateRound(this, wantIds, peerHas.size()); if (wantAll.isEmpty() && !wantIds.isEmpty()) @@ -1754,6 +1765,18 @@ public class UploadPack { // create a pack at this point, let the client know so it stops // telling us about its history. // + if (option != Option.WAIT_FOR_DONE) { + sentReady = shouldGiveUp(peerHas, out, missCnt); + } + + preUploadHook.onEndNegotiateRound(this, wantAll, haveCnt, missCnt, sentReady); + peerHas.clear(); + return last; + } + + private boolean shouldGiveUp(List<ObjectId> peerHas, PacketLineOut out, int missCnt) + throws IOException { + boolean sentReady = false; boolean didOkToGiveUp = false; if (0 < missCnt) { for (int i = peerHas.size() - 1; i >= 0; i--) { @@ -1765,10 +1788,12 @@ public class UploadPack { case OFF: break; case CONTINUE: - out.writeString("ACK " + id.name() + " continue\n"); //$NON-NLS-1$ //$NON-NLS-2$ + out.writeString( + "ACK " + id.name() + " continue\n"); //$NON-NLS-1$ //$NON-NLS-2$ break; case DETAILED: - out.writeString("ACK " + id.name() + " ready\n"); //$NON-NLS-1$ //$NON-NLS-2$ + out.writeString( + "ACK " + id.name() + " ready\n"); //$NON-NLS-1$ //$NON-NLS-2$ sentReady = true; break; } @@ -1778,15 +1803,14 @@ public class UploadPack { } } - if (multiAck == MultiAck.DETAILED && !didOkToGiveUp && okToGiveUp()) { + if (multiAck == MultiAck.DETAILED && !didOkToGiveUp + && okToGiveUp()) { ObjectId id = peerHas.get(peerHas.size() - 1); out.writeString("ACK " + id.name() + " ready\n"); //$NON-NLS-1$ //$NON-NLS-2$ sentReady = true; } - preUploadHook.onEndNegotiateRound(this, wantAll, haveCnt, missCnt, sentReady); - peerHas.clear(); - return last; + return sentReady; } private void parseWants(PackStatistics.Accumulator accumulator) throws IOException { |