From 2a5c8cb46c797b756b247d57f70a90d3939e149c Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Tue, 6 Oct 2009 18:43:41 -0700 Subject: [PATCH] Teach ReceivePack how to use an RPC style interface If biDirectionalPipe is false ReceivePack does not start out with the advertisement but instead assumes it should read the command set once, process that, and write the status report out. This means it only is doing one read through the input followed by one write to the output, which fits with the HTTP request processing model, and any other type of RPC system... assuming that the payload for input can be a very big entity like the command stream followed by the pack file. Change-Id: I6f31f6537a3b7498803a8a54e10b0622105718c1 Signed-off-by: Shawn O. Pearce --- .../eclipse/jgit/transport/ReceivePack.java | 45 ++++++++++++++++++- 1 file changed, 43 insertions(+), 2 deletions(-) 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 d87395c1c..4ba446edb 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java @@ -96,6 +96,19 @@ public class ReceivePack { /** Revision traversal support over {@link #db}. */ private final RevWalk walk; + /** + * Is the client connection a bi-directional socket or pipe? + *

+ * If true, this class assumes it can perform multiple read and write cycles + * with the client over the input and output streams. This matches the + * functionality available with a standard TCP/IP connection, or a local + * operating system or in-memory pipe. + *

+ * If false, this class runs in a read everything then output results mode, + * making it suitable for single round-trip systems RPCs such as HTTP. + */ + private boolean biDirectionalPipe = true; + /** Should an incoming transfer validate objects? */ private boolean checkReceivedObjects; @@ -219,6 +232,27 @@ public final Map getAdvertisedRefs() { return refs; } + /** + * @return true if this class expects a bi-directional pipe opened between + * the client and itself. The default is true. + */ + public boolean isBiDirectionalPipe() { + return biDirectionalPipe; + } + + /** + * @param twoWay + * if true, this class will assume the socket is a fully + * bidirectional pipe between the two peers and takes advantage + * of that by first transmitting the known refs, then waiting to + * read commands. If false, this class assumes it must read the + * commands before writing output and does not perform the + * initial advertising. + */ + public void setBiDirectionalPipe(final boolean twoWay) { + biDirectionalPipe = twoWay; + } + /** * @return true if this instance will verify received objects are formatted * correctly. Validating objects requires more CPU time on this side @@ -484,7 +518,10 @@ public void println() { } private void service() throws IOException { - sendAdvertisedRefs(); + if (biDirectionalPipe) + sendAdvertisedRefs(); + else + refs = db.getAllRefs(); recvCommands(); if (!commands.isEmpty()) { enableCapabilities(); @@ -587,7 +624,11 @@ private void recvCommands() throws IOException { final ObjectId newId = ObjectId.fromString(line.substring(41, 81)); final String name = line.substring(82); final ReceiveCommand cmd = new ReceiveCommand(oldId, newId, name); - cmd.setRef(refs.get(cmd.getRefName())); + if (name.equals(Constants.HEAD)) { + cmd.setResult(Result.REJECTED_CURRENT_BRANCH); + } else { + cmd.setRef(refs.get(cmd.getRefName())); + } commands.add(cmd); } }