From 08a77c04b4574ca4b282154d4ed4ab85cf2fcaa2 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Sat, 23 Jan 2010 13:11:58 -0800 Subject: [PATCH] Check for remote server exec failures and report If remote.name.uploadpack or .receivepack is misconfigured and points to a non-existent command on the remote system, we should receive back exit status 127. Report this case specially with the command we used so the user knows what is going. Bug: 293703 Change-Id: I7504e7b6238d5d8e698d37db7411c4817a039d08 Signed-off-by: Shawn O. Pearce --- .../jgit/transport/TransportGitSsh.java | 56 +++++++++++++------ 1 file changed, 40 insertions(+), 16 deletions(-) diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitSsh.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitSsh.java index 55636f8dc..5ee7887f6 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitSsh.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitSsh.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2009, Google Inc. + * Copyright (C) 2008-2010, Google Inc. * Copyright (C) 2008, Marek Zawirski * Copyright (C) 2008, Robin Rosenberg * Copyright (C) 2008, Shawn O. Pearce @@ -127,6 +127,23 @@ private static void sq(final StringBuilder cmd, final String val) { cmd.append(QuotedString.BOURNE.quote(val)); } + private String commandFor(final String exe) { + String path = uri.getPath(); + if (uri.getScheme() != null && uri.getPath().startsWith("/~")) + path = (uri.getPath().substring(1)); + + final StringBuilder cmd = new StringBuilder(); + final int gitspace = exe.indexOf("git "); + if (gitspace >= 0) { + sqMinimal(cmd, exe.substring(0, gitspace + 3)); + cmd.append(' '); + sqMinimal(cmd, exe.substring(gitspace + 4)); + } else + sqMinimal(cmd, exe); + cmd.append(' '); + sqAlways(cmd, path); + return cmd.toString(); + } ChannelExec exec(final String exe) throws TransportException { initSession(); @@ -134,21 +151,7 @@ ChannelExec exec(final String exe) throws TransportException { final int tms = getTimeout() > 0 ? getTimeout() * 1000 : 0; try { final ChannelExec channel = (ChannelExec) sock.openChannel("exec"); - String path = uri.getPath(); - if (uri.getScheme() != null && uri.getPath().startsWith("/~")) - path = (uri.getPath().substring(1)); - - final StringBuilder cmd = new StringBuilder(); - final int gitspace = exe.indexOf("git "); - if (gitspace >= 0) { - sqMinimal(cmd, exe.substring(0, gitspace + 3)); - cmd.append(' '); - sqMinimal(cmd, exe.substring(gitspace + 4)); - } else - sqMinimal(cmd, exe); - cmd.append(' '); - sqAlways(cmd, path); - channel.setCommand(cmd.toString()); + channel.setCommand(commandFor(exe)); errStream = createErrorStream(); channel.setErrStream(errStream, true); channel.connect(tms); @@ -158,6 +161,17 @@ ChannelExec exec(final String exe) throws TransportException { } } + void checkExecFailure(int status, String exe) throws TransportException { + if (status == 127) { + String why = errStream.toString(); + IOException cause = null; + if (why != null && why.length() > 0) + cause = new IOException(why); + throw new TransportException(uri, "cannot execute: " + + commandFor(exe), cause); + } + } + /** * @return the error stream for the channel, the stream is used to detect * specific error reasons for exceptions. @@ -305,6 +319,8 @@ public void run() { class SshFetchConnection extends BasePackFetchConnection { private ChannelExec channel; + private int exitStatus; + SshFetchConnection() throws TransportException { super(TransportGitSsh.this); try { @@ -327,6 +343,8 @@ class SshFetchConnection extends BasePackFetchConnection { try { readAdvertisedRefs(); } catch (NoRemoteRepositoryException notFound) { + close(); + checkExecFailure(exitStatus, getOptionUploadPack()); throw cleanNotFound(notFound); } } @@ -337,6 +355,7 @@ public void close() { if (channel != null) { try { + exitStatus = channel.getExitStatus(); if (channel.isConnected()) channel.disconnect(); } finally { @@ -349,6 +368,8 @@ public void close() { class SshPushConnection extends BasePackPushConnection { private ChannelExec channel; + private int exitStatus; + SshPushConnection() throws TransportException { super(TransportGitSsh.this); try { @@ -371,6 +392,8 @@ class SshPushConnection extends BasePackPushConnection { try { readAdvertisedRefs(); } catch (NoRemoteRepositoryException notFound) { + close(); + checkExecFailure(exitStatus, getOptionReceivePack()); throw cleanNotFound(notFound); } } @@ -381,6 +404,7 @@ public void close() { if (channel != null) { try { + exitStatus = channel.getExitStatus(); if (channel.isConnected()) channel.disconnect(); } finally {