aboutsummaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit
diff options
context:
space:
mode:
authorShawn O. Pearce <spearce@spearce.org>2010-02-11 10:58:22 -0800
committerShawn O. Pearce <spearce@spearce.org>2010-03-12 16:08:14 -0800
commitd8c3e98d73a4fb7409580a7d9f3395ac506f7e5d (patch)
tree37c499a7738a21d5680f4699863e1028c9b2de7b /org.eclipse.jgit
parent1f4a30b80d734d28baeb48fb45013716f0afb7a4 (diff)
downloadjgit-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.java39
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);