diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackPushConnection.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackPushConnection.java index 2603ca287..6e8b05da2 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackPushConnection.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackPushConnection.java @@ -86,6 +86,8 @@ class BasePackPushConnection extends BasePackConnection implements static final String CAPABILITY_OFS_DELTA = "ofs-delta"; + static final String CAPABILITY_SIDE_BAND_64K = "side-band-64k"; + private final boolean thinPack; private boolean capableDeleteRefs; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java index 4d63ee68e..c5bbdac5a 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java @@ -43,13 +43,20 @@ package org.eclipse.jgit.transport; -import java.io.BufferedWriter; +import static org.eclipse.jgit.transport.BasePackPushConnection.CAPABILITY_DELETE_REFS; +import static org.eclipse.jgit.transport.BasePackPushConnection.CAPABILITY_OFS_DELTA; +import static org.eclipse.jgit.transport.BasePackPushConnection.CAPABILITY_REPORT_STATUS; +import static org.eclipse.jgit.transport.BasePackPushConnection.CAPABILITY_SIDE_BAND_64K; +import static org.eclipse.jgit.transport.SideBandOutputStream.CH_DATA; +import static org.eclipse.jgit.transport.SideBandOutputStream.CH_PROGRESS; +import static org.eclipse.jgit.transport.SideBandOutputStream.MAX_BUF; + import java.io.EOFException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; -import java.io.PrintWriter; +import java.io.Writer; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; @@ -84,12 +91,6 @@ * Implements the server side of a push connection, receiving objects. */ public class ReceivePack { - static final String CAPABILITY_REPORT_STATUS = BasePackPushConnection.CAPABILITY_REPORT_STATUS; - - static final String CAPABILITY_DELETE_REFS = BasePackPushConnection.CAPABILITY_DELETE_REFS; - - static final String CAPABILITY_OFS_DELTA = BasePackPushConnection.CAPABILITY_OFS_DELTA; - /** Database we write the stored objects into. */ private final Repository db; @@ -151,7 +152,7 @@ public class ReceivePack { private PacketLineOut pckOut; - private PrintWriter msgs; + private Writer msgs; /** The refs we advertised as existing at the start of the connection. */ private Map refs; @@ -165,9 +166,12 @@ public class ReceivePack { /** An exception caught while unpacking and fsck'ing the objects. */ private Throwable unpackError; - /** if {@link #enabledCapablities} has {@link #CAPABILITY_REPORT_STATUS} */ + /** If {@link BasePackPushConnection#CAPABILITY_REPORT_STATUS} is enabled. */ private boolean reportStatus; + /** If {@link BasePackPushConnection#CAPABILITY_SIDE_BAND_64K} is enabled. */ + private boolean sideBand; + /** Lock around the received pack file, while updating refs. */ private PackLock packLock; @@ -440,7 +444,12 @@ public List getAllCommands() { * string must not end with an LF, and must not contain an LF. */ public void sendError(final String what) { - sendMessage("error", what); + try { + if (msgs != null) + msgs.write("error: " + what + "\n"); + } catch (IOException e) { + // Ignore write failures. + } } /** @@ -454,12 +463,12 @@ public void sendError(final String what) { * string must not end with an LF, and must not contain an LF. */ public void sendMessage(final String what) { - sendMessage("remote", what); - } - - private void sendMessage(final String type, final String what) { - if (msgs != null) - msgs.println(type + ": " + what); + try { + if (msgs != null) + msgs.write(what + "\n"); + } catch (IOException e) { + // Ignore write failures. + } } /** @@ -499,16 +508,8 @@ public void receive(final InputStream input, final OutputStream output, pckIn = new PacketLineIn(rawIn); pckOut = new PacketLineOut(rawOut); - if (messages != null) { - msgs = new PrintWriter(new BufferedWriter( - new OutputStreamWriter(messages, Constants.CHARSET), - 8192)) { - @Override - public void println() { - print('\n'); - } - }; - } + if (messages != null) + msgs = new OutputStreamWriter(messages, Constants.CHARSET); enabledCapablities = new HashSet(); commands = new ArrayList(); @@ -516,8 +517,19 @@ public void println() { service(); } finally { try { - if (msgs != null) { + if (pckOut != null) + pckOut.flush(); + if (msgs != null) msgs.flush(); + + if (sideBand) { + // If we are using side band, we need to send a final + // flush-pkt to tell the remote peer the side band is + // complete and it should stop decoding. We need to + // use the original output stream as rawOut is now the + // side band data channel. + // + new PacketLineOut(output).end(); } } finally { unlockPack(); @@ -581,10 +593,9 @@ void sendString(final String s) throws IOException { } else if (msgs != null) { sendStatusReport(false, new Reporter() { void sendString(final String s) throws IOException { - msgs.println(s); + msgs.write(s + "\n"); } }); - msgs.flush(); } postReceive.onPostReceive(this, filterCommands(Result.OK)); @@ -609,6 +620,7 @@ private void unlockPack() { public void sendAdvertisedRefs(final RefAdvertiser adv) throws IOException { final RevFlag advertised = walk.newFlag("ADVERTISED"); adv.init(walk, advertised); + adv.advertiseCapability(CAPABILITY_SIDE_BAND_64K); adv.advertiseCapability(CAPABILITY_DELETE_REFS); adv.advertiseCapability(CAPABILITY_REPORT_STATUS); if (allowOfsDelta) @@ -667,6 +679,16 @@ private void recvCommands() throws IOException { private void enableCapabilities() { reportStatus = enabledCapablities.contains(CAPABILITY_REPORT_STATUS); + + sideBand = enabledCapablities.contains(CAPABILITY_SIDE_BAND_64K); + if (sideBand) { + OutputStream out = rawOut; + + rawOut = new SideBandOutputStream(CH_DATA, MAX_BUF, out); + pckOut = new PacketLineOut(rawOut); + msgs = new OutputStreamWriter(new SideBandOutputStream(CH_PROGRESS, + MAX_BUF, out), Constants.CHARSET); + } } private boolean needPack() {