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 4c9c2f6f1..347fd9330 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java @@ -673,6 +673,7 @@ public abstract class BasePackFetchConnection extends BasePackConnection } private void receivePack(final ProgressMonitor monitor) throws IOException { + onReceivePack(); InputStream input = in; if (sideband) input = new SideBandInputStream(input, monitor, getMessageWriter()); @@ -690,6 +691,15 @@ public abstract class BasePackFetchConnection extends BasePackConnection } } + /** + * Notification event delivered just before the pack is received from the + * network. This event can be used by RPC such as {@link TransportHttp} to + * disable its request magic and ensure the pack stream is read correctly. + */ + protected void onReceivePack() { + // By default do nothing for TCP based protocols. + } + private static class CancelledException extends Exception { private static final long serialVersionUID = 1L; } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java index b323f2b5a..862d08307 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java @@ -687,6 +687,8 @@ public class TransportHttp extends HttpTransport implements WalkTransport, } class SmartHttpFetchConnection extends BasePackFetchConnection { + private Service svc; + SmartHttpFetchConnection(final InputStream advertisement) throws TransportException { super(TransportHttp.this); @@ -701,9 +703,18 @@ public class TransportHttp extends HttpTransport implements WalkTransport, protected void doFetch(final ProgressMonitor monitor, final Collection want, final Set have) throws TransportException { - final Service svc = new Service(SVC_UPLOAD_PACK); - init(svc.in, svc.out); - super.doFetch(monitor, want, have); + try { + svc = new Service(SVC_UPLOAD_PACK); + init(svc.in, svc.out); + super.doFetch(monitor, want, have); + } finally { + svc = null; + } + } + + @Override + protected void onReceivePack() { + svc.finalRequest = true; } } @@ -756,6 +767,8 @@ public class TransportHttp extends HttpTransport implements WalkTransport, private final HttpExecuteStream execute; + boolean finalRequest; + final UnionInputStream in; final HttpOutputStream out; @@ -784,10 +797,14 @@ public class TransportHttp extends HttpTransport implements WalkTransport, out.close(); if (conn == null) { - // Output hasn't started yet, because everything fit into - // our request buffer. Send with a Content-Length header. - // if (out.length() == 0) { + // Request output hasn't started yet, but more data is being + // requested. If there is no request data buffered and the + // final request was already sent, do nothing to ensure the + // caller is shown EOF on the InputStream; otherwise an + // programming error has occurred within this module. + if (finalRequest) + return; throw new TransportException(uri, JGitText.get().startingReadStageWithoutWrittenRequestDataPendingIsNotSupported); } @@ -833,7 +850,8 @@ public class TransportHttp extends HttpTransport implements WalkTransport, } in.add(openInputStream(conn)); - in.add(execute); + if (!finalRequest) + in.add(execute); conn = null; }