@ -58,6 +58,7 @@ 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_SIDE_BAND_64K ;
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_THIN_PACK ;
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_THIN_PACK ;
import java.io.ByteArrayOutputStream ;
import java.io.EOFException ;
import java.io.EOFException ;
import java.io.IOException ;
import java.io.IOException ;
import java.io.InputStream ;
import java.io.InputStream ;
@ -71,6 +72,7 @@ import java.util.List;
import java.util.Map ;
import java.util.Map ;
import java.util.Set ;
import java.util.Set ;
import org.eclipse.jgit.annotations.Nullable ;
import org.eclipse.jgit.errors.CorruptObjectException ;
import org.eclipse.jgit.errors.CorruptObjectException ;
import org.eclipse.jgit.errors.IncorrectObjectTypeException ;
import org.eclipse.jgit.errors.IncorrectObjectTypeException ;
import org.eclipse.jgit.errors.MissingObjectException ;
import org.eclipse.jgit.errors.MissingObjectException ;
@ -235,7 +237,7 @@ public class UploadPack {
private InputStream rawIn ;
private InputStream rawIn ;
private OutputStream rawOut ;
private ResponseBuffered OutputStream rawOut ;
private PacketLineIn pckIn ;
private PacketLineIn pckIn ;
@ -644,11 +646,10 @@ public class UploadPack {
* other network connections this should be null .
* other network connections this should be null .
* @throws IOException
* @throws IOException
* /
* /
public void upload ( final InputStream input , final OutputStream output ,
public void upload ( final InputStream input , OutputStream output ,
final OutputStream messages ) throws IOException {
final OutputStream messages ) throws IOException {
try {
try {
rawIn = input ;
rawIn = input ;
rawOut = output ;
if ( messages ! = null )
if ( messages ! = null )
msgOut = messages ;
msgOut = messages ;
@ -656,11 +657,17 @@ public class UploadPack {
final Thread caller = Thread . currentThread ( ) ;
final Thread caller = Thread . currentThread ( ) ;
timer = new InterruptTimer ( caller . getName ( ) + "-Timer" ) ; //$NON-NLS-1$
timer = new InterruptTimer ( caller . getName ( ) + "-Timer" ) ; //$NON-NLS-1$
TimeoutInputStream i = new TimeoutInputStream ( rawIn , timer ) ;
TimeoutInputStream i = new TimeoutInputStream ( rawIn , timer ) ;
TimeoutOutputStream o = new TimeoutOutputStream ( rawOut , timer ) ;
@SuppressWarnings ( "resource" )
TimeoutOutputStream o = new TimeoutOutputStream ( output , timer ) ;
i . setTimeout ( timeout * 1000 ) ;
i . setTimeout ( timeout * 1000 ) ;
o . setTimeout ( timeout * 1000 ) ;
o . setTimeout ( timeout * 1000 ) ;
rawIn = i ;
rawIn = i ;
rawOut = o ;
output = o ;
}
rawOut = new ResponseBufferedOutputStream ( output ) ;
if ( biDirectionalPipe ) {
rawOut . stopBuffering ( ) ;
}
}
pckIn = new PacketLineIn ( rawIn ) ;
pckIn = new PacketLineIn ( rawIn ) ;
@ -714,6 +721,8 @@ public class UploadPack {
private void service ( ) throws IOException {
private void service ( ) throws IOException {
boolean sendPack ;
boolean sendPack ;
// If it's a non-bidi request, we need to read the entire request before
// writing a response. Buffer the response until then.
try {
try {
if ( biDirectionalPipe )
if ( biDirectionalPipe )
sendAdvertisedRefs ( new PacketLineOutRefAdvertiser ( pckOut ) ) ;
sendAdvertisedRefs ( new PacketLineOutRefAdvertiser ( pckOut ) ) ;
@ -769,6 +778,8 @@ public class UploadPack {
throw new UploadPackInternalServerErrorException ( err ) ;
throw new UploadPackInternalServerErrorException ( err ) ;
}
}
throw err ;
throw err ;
} finally {
rawOut . stopBuffering ( ) ;
}
}
if ( sendPack )
if ( sendPack )
@ -1572,4 +1583,50 @@ public class UploadPack {
adv . addSymref ( Constants . HEAD , head . getLeaf ( ) . getName ( ) ) ;
adv . addSymref ( Constants . HEAD , head . getLeaf ( ) . getName ( ) ) ;
}
}
}
}
private static class ResponseBufferedOutputStream extends OutputStream {
private final OutputStream rawOut ;
private OutputStream out ;
@Nullable
private ByteArrayOutputStream buffer ;
ResponseBufferedOutputStream ( OutputStream rawOut ) {
this . rawOut = rawOut ;
this . out = this . buffer = new ByteArrayOutputStream ( ) ;
}
@Override
public void write ( int b ) throws IOException {
out . write ( b ) ;
}
@Override
public void write ( byte b [ ] ) throws IOException {
out . write ( b ) ;
}
@Override
public void write ( byte b [ ] , int off , int len ) throws IOException {
out . write ( b , off , len ) ;
}
@Override
public void flush ( ) throws IOException {
out . flush ( ) ;
}
@Override
public void close ( ) throws IOException {
out . close ( ) ;
}
void stopBuffering ( ) throws IOException {
if ( buffer ! = null ) {
buffer . writeTo ( rawOut ) ;
buffer = null ;
out = rawOut ;
}
}
}
}
}