Browse Source

Enable smart HTTP transport to place EOF at end of pack

When fetching over smart HTTP the InputStream that gets fed into
a PackParser doesn't really support EOF at the end of the pack. It
instead tries to make a new HTTP request, which fails because there
is no request body currently buffered by the client.

Make EOF work correctly on the end of an HTTP derived InputStream
for the pack by denoting no more requests are expected as the higher
level code is now consuming the pack (or side-band embedded pack).
Smart HTTP support doesn't automatically enqueue execute support onto
the end of the UnionInputStream, which allows the UnionInputStream
to correctly reflect EOF when the HTTP response is consumed.

Change-Id: I975f1ab1c81ab1c1af925716970088bc7b8d6b1a
stable-2.0
Shawn O. Pearce 13 years ago
parent
commit
dfff04742f
  1. 10
      org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java
  2. 32
      org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java

10
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;
}

32
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<Ref> want, final Set<ObjectId> 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;
}

Loading…
Cancel
Save