diff options
author | Shawn O. Pearce <spearce@spearce.org> | 2010-02-11 10:58:22 -0800 |
---|---|---|
committer | Shawn O. Pearce <spearce@spearce.org> | 2010-03-12 16:08:14 -0800 |
commit | d8c3e98d73a4fb7409580a7d9f3395ac506f7e5d (patch) | |
tree | 37c499a7738a21d5680f4699863e1028c9b2de7b /org.eclipse.jgit | |
parent | 1f4a30b80d734d28baeb48fb45013716f0afb7a4 (diff) | |
download | jgit-d8c3e98d73a4fb7409580a7d9f3395ac506f7e5d.tar.gz jgit-d8c3e98d73a4fb7409580a7d9f3395ac506f7e5d.zip |
Use "ERR message" for early ReceivePack problems
If the application wants to, it can use sendError(String) to send one
or more error messages to clients before the advertisements are sent.
These will cause a C Git client to break out of the advertisement
parsing loop, display "remote error: message\n", and terminate.
Servers can optionally use this to send a detailed error to a client
explaining why it cannot use the ReceivePack service on a repository.
Over smart HTTP these errors are sent in a 200 OK response, and
are in the payload, allowing the Git client to give the end-user
the custom message rather than the generic error "403 Forbidden".
Change-Id: I03f4345183765d21002118617174c77f71427b5a
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Diffstat (limited to 'org.eclipse.jgit')
-rw-r--r-- | org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java | 39 |
1 files changed, 31 insertions, 8 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 c5bbdac5a3..d799658709 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java @@ -163,6 +163,9 @@ public class ReceivePack { /** Commands to execute, as received by the client. */ private List<ReceiveCommand> commands; + /** Error to display instead of advertising the references. */ + private StringBuilder advertiseError; + /** An exception caught while unpacking and fsck'ing the objects. */ private Throwable unpackError; @@ -428,10 +431,17 @@ public class ReceivePack { } /** - * Send an error message to the client, if it supports receiving them. + * Send an error message to the client. * <p> - * If the client doesn't support receiving messages, the message will be - * discarded, with no other indication to the caller or to the client. + * If any error messages are sent before the references are advertised to + * the client, the errors will be sent instead of the advertisement and the + * receive operation will be aborted. All clients should receive and display + * such early stage errors. + * <p> + * If the reference advertisements have already been sent, messages are sent + * in a side channel. If the client doesn't support receiving messages, the + * message will be discarded, with no other indication to the caller or to + * the client. * <p> * {@link PreReceiveHook}s should always try to use * {@link ReceiveCommand#setResult(Result, String)} with a result status of @@ -444,11 +454,17 @@ public class ReceivePack { * string must not end with an LF, and must not contain an LF. */ public void sendError(final String what) { - try { - if (msgs != null) - msgs.write("error: " + what + "\n"); - } catch (IOException e) { - // Ignore write failures. + if (refs == null) { + if (advertiseError == null) + advertiseError = new StringBuilder(); + advertiseError.append(what).append('\n'); + } else { + try { + if (msgs != null) + msgs.write("error: " + what + "\n"); + } catch (IOException e) { + // Ignore write failures. + } } } @@ -558,6 +574,8 @@ public class ReceivePack { sendAdvertisedRefs(new PacketLineOutRefAdvertiser(pckOut)); else refs = refFilter.filter(db.getAllRefs()); + if (advertiseError != null) + return; recvCommands(); if (!commands.isEmpty()) { enableCapabilities(); @@ -618,6 +636,11 @@ public class ReceivePack { * the formatter failed to write an advertisement. */ public void sendAdvertisedRefs(final RefAdvertiser adv) throws IOException { + if (advertiseError != null) { + adv.writeOne("ERR " + advertiseError); + return; + } + final RevFlag advertised = walk.newFlag("ADVERTISED"); adv.init(walk, advertised); adv.advertiseCapability(CAPABILITY_SIDE_BAND_64K); |