]> source.dussan.org Git - jgit.git/commitdiff
Enable smart HTTP transport to place EOF at end of pack 48/5348/2
authorShawn O. Pearce <spearce@spearce.org>
Tue, 13 Mar 2012 18:10:33 +0000 (11:10 -0700)
committerShawn O. Pearce <spearce@spearce.org>
Tue, 13 Mar 2012 18:41:51 +0000 (11:41 -0700)
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

org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java
org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java

index 4c9c2f6f14a1d18b9d7d1108e9874f85249b7381..347fd93305385aa2894cb2172afde3de255edecb 100644 (file)
@@ -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;
        }
index b323f2b5aeeb3fc74ebeb242c233e525c37b0bd4..862d08307f9ea4e0888abbcd363481883d8dd754 100644 (file)
@@ -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;
                }