diff options
Diffstat (limited to 'org.eclipse.jgit')
4 files changed, 159 insertions, 37 deletions
diff --git a/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties b/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties index 165ad9d401..570895e810 100644 --- a/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties +++ b/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties @@ -224,6 +224,7 @@ indexSignatureIsInvalid=Index signature is invalid: {0} indexWriteException=Modified index could not be written integerValueOutOfRange=Integer value {0}.{1} out of range internalRevisionError=internal revision error +internalServerError=internal server error interruptedWriting=Interrupted writing {0} inTheFuture=in the future invalidAdvertisementOf=invalid advertisement of {0} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java b/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java index c0f7a1479c..7054cf800f 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java @@ -284,6 +284,7 @@ public class JGitText extends TranslationBundle { /***/ public String indexWriteException; /***/ public String integerValueOutOfRange; /***/ public String internalRevisionError; + /***/ public String internalServerError; /***/ public String interruptedWriting; /***/ public String inTheFuture; /***/ public String invalidAdvertisementOf; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java index 0e50b937b6..41f64a163c 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java @@ -401,25 +401,62 @@ public class UploadPack { } } - recvWants(); - if (wantIds.isEmpty()) { - preUploadHook.onBeginNegotiateRound(this, wantIds, 0); - preUploadHook.onEndNegotiateRound(this, wantIds, 0, 0, false); - return; - } + boolean sendPack; + try { + recvWants(); + if (wantIds.isEmpty()) { + preUploadHook.onBeginNegotiateRound(this, wantIds, 0); + preUploadHook.onEndNegotiateRound(this, wantIds, 0, 0, false); + return; + } - if (options.contains(OPTION_MULTI_ACK_DETAILED)) { - multiAck = MultiAck.DETAILED; - noDone = options.contains(OPTION_NO_DONE); - } else if (options.contains(OPTION_MULTI_ACK)) - multiAck = MultiAck.CONTINUE; - else - multiAck = MultiAck.OFF; + if (options.contains(OPTION_MULTI_ACK_DETAILED)) { + multiAck = MultiAck.DETAILED; + noDone = options.contains(OPTION_NO_DONE); + } else if (options.contains(OPTION_MULTI_ACK)) + multiAck = MultiAck.CONTINUE; + else + multiAck = MultiAck.OFF; + + sendPack = negotiate(); + } catch (PackProtocolException err) { + reportErrorDuringNegotiate(err.getMessage()); + throw err; + + } catch (UploadPackMayNotContinueException err) { + if (!err.isOutput() && err.getMessage() != null) { + try { + pckOut.writeString("ERR " + err.getMessage() + "\n"); + err.setOutput(); + } catch (Throwable err2) { + // Ignore this secondary failure (and not mark output). + } + } + throw err; + + } catch (IOException err) { + reportErrorDuringNegotiate(JGitText.get().internalServerError); + throw err; + } catch (RuntimeException err) { + reportErrorDuringNegotiate(JGitText.get().internalServerError); + throw err; + } catch (Error err) { + reportErrorDuringNegotiate(JGitText.get().internalServerError); + throw err; + } - if (negotiate()) + if (sendPack) sendPack(); } + private void reportErrorDuringNegotiate(String msg) { + try { + pckOut.writeString("ERR " + msg + "\n"); + } catch (Throwable err) { + // Ignore this secondary failure. + } + } + /** * Generate an advertisement of available refs and capabilities. * @@ -536,16 +573,7 @@ public class UploadPack { private ObjectId processHaveLines(List<ObjectId> peerHas, ObjectId last) throws IOException { - try { - preUploadHook.onBeginNegotiateRound(this, wantIds, peerHas.size()); - } catch (UploadPackMayNotContinueException fail) { - if (fail.getMessage() != null) { - pckOut.writeString("ERR " + fail.getMessage() + "\n"); - fail.setOutput(); - } - throw fail; - } - + preUploadHook.onBeginNegotiateRound(this, wantIds, peerHas.size()); if (peerHas.isEmpty()) return last; @@ -576,7 +604,6 @@ public class UploadPack { if (wantIds.contains(id)) { String msg = MessageFormat.format( JGitText.get().wantNotValid, id.name()); - pckOut.writeString("ERR " + msg); throw new PackProtocolException(msg, notFound); } continue; @@ -591,7 +618,6 @@ public class UploadPack { if (!advertised.contains(obj)) { String msg = MessageFormat.format( JGitText.get().wantNotValid, obj.name()); - pckOut.writeString("ERR " + msg); throw new PackProtocolException(msg); } @@ -689,17 +715,7 @@ public class UploadPack { sentReady = true; } - try { - preUploadHook.onEndNegotiateRound(this, wantAll, // - haveCnt, missCnt, sentReady); - } catch (UploadPackMayNotContinueException fail) { - if (fail.getMessage() != null) { - pckOut.writeString("ERR " + fail.getMessage() + "\n"); - fail.setOutput(); - } - throw fail; - } - + preUploadHook.onEndNegotiateRound(this, wantAll, haveCnt, missCnt, sentReady); peerHas.clear(); return last; } @@ -768,6 +784,49 @@ public class UploadPack { "\\x" + Integer.toHexString(eof))); } + if (sideband) { + try { + sendPack(true); + } catch (UploadPackMayNotContinueException noPack) { + // This was already reported on (below). + throw noPack; + } catch (IOException err) { + if (reportInternalServerErrorOverSideband()) + throw new UploadPackInternalServerErrorException(err); + else + throw err; + } catch (RuntimeException err) { + if (reportInternalServerErrorOverSideband()) + throw new UploadPackInternalServerErrorException(err); + else + throw err; + } catch (Error err) { + if (reportInternalServerErrorOverSideband()) + throw new UploadPackInternalServerErrorException(err); + else + throw err; + } + } else { + sendPack(false); + } + } + + private boolean reportInternalServerErrorOverSideband() { + try { + SideBandOutputStream err = new SideBandOutputStream( + SideBandOutputStream.CH_ERROR, + SideBandOutputStream.SMALL_BUF, + rawOut); + err.write(Constants.encode(JGitText.get().internalServerError)); + err.flush(); + return true; + } catch (Throwable cannotReport) { + // Ignore the reason. This is a secondary failure. + return false; + } + } + + private void sendPack(final boolean sideband) throws IOException { ProgressMonitor pm = NullProgressMonitor.INSTANCE; OutputStream packOut = rawOut; SideBandOutputStream msgOut = null; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPackInternalServerErrorException.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPackInternalServerErrorException.java new file mode 100644 index 0000000000..0636984dcf --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPackInternalServerErrorException.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2011, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.transport; + +import java.io.IOException; + +/** UploadPack has already reported an error to the client. */ +public class UploadPackInternalServerErrorException extends IOException { + private static final long serialVersionUID = 1L; + + /** + * Initialize a new exception. + * + * @param why + * root cause. + */ + public UploadPackInternalServerErrorException(Throwable why) { + super(why); + } +} |