From 0cfce83603b9ee2afdbdc586f49f02d862be9f00 Mon Sep 17 00:00:00 2001 From: Segev Finer Date: Fri, 23 Dec 2016 23:49:02 +0200 Subject: [PATCH] squash! connect: recognize [tortoise]plink in GIT_SSH_COMMAND connect: handle putty/plink also in GIT_SSH_COMMAND Git for Windows has special support for the popular SSH client PuTTY: when using PuTTY's non-interactive version ("plink.exe"), we use the -P option to specify the port rather than OpenSSH's -p option. TortoiseGit ships with its own, forked version of plink.exe, that adds support for the -batch option, and for good measure we special-case that, too. However, this special-casing of PuTTY only covers the case where the user overrides the SSH command via the environment variable GIT_SSH (which allows specifying the name of the executable), not GIT_SSH_COMMAND (which allows specifying a full command, including additional command-line options). When users want to pass any additional arguments to (Tortoise-)Plink, such as setting a private key, they are required to either use a shell script named plink or tortoiseplink or duplicate the logic that is already in Git for passing the correct style of command line arguments, which can be difficult, error prone and annoying to get right. This patch simply reuses the existing logic and expands it to cover GIT_SSH_COMMAND, too. Note: it may look a little heavy-handed to duplicate the entire command-line and then split it, only to extract the name of the executable. However, this is not a performance-critical code path, and the code is much more readable this way. Signed-off-by: Segev Finer Signed-off-by: Johannes Schindelin --- connect.c | 13 +++++-------- t/t5601-clone.sh | 11 +++++++---- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/connect.c b/connect.c index 746dd27a18..c81f77001b 100644 --- a/connect.c +++ b/connect.c @@ -794,14 +794,13 @@ struct child_process *git_connect(int fd[2], const char *url, ssh = get_ssh_command(); if (ssh) { - char* split_ssh; - const char** ssh_argv; + char *split_ssh = xstrdup(ssh); + const char **ssh_argv; - split_ssh = xstrdup(ssh); - if (split_cmdline(split_ssh, &ssh_argv) >= 1) { + if (split_cmdline(split_ssh, &ssh_argv)) ssh_argv0 = xstrdup(ssh_argv[0]); - } free(split_ssh); + free((void *)ssh_argv); } else { /* * GIT_SSH is the no-shell version of @@ -818,9 +817,7 @@ struct child_process *git_connect(int fd[2], const char *url, } if (ssh_argv0) { - const char *base; - - base = basename(ssh_argv0); + const char *base = basename(ssh_argv0); tortoiseplink = !strcasecmp(base, "tortoiseplink") || !strcasecmp(base, "tortoiseplink.exe"); diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh index ff6bb9f643..5b228e2675 100755 --- a/t/t5601-clone.sh +++ b/t/t5601-clone.sh @@ -386,15 +386,18 @@ test_expect_success 'tortoiseplink is like putty, with extra arguments' ' expect_ssh "-batch -P 123" myhost src ' -test_expect_success 'double quoted plink.exe is treated specially (as putty) in GIT_SSH_COMMAND' ' +test_expect_success 'double quoted plink.exe in GIT_SSH_COMMAND' ' copy_ssh_wrapper_as "$TRASH_DIRECTORY/plink.exe" && - GIT_SSH_COMMAND="\"$TRASH_DIRECTORY/plink.exe\" -v" git clone "[myhost:123]:src" ssh-bracket-clone-plink-3 && + GIT_SSH_COMMAND="\"$TRASH_DIRECTORY/plink.exe\" -v" \ + git clone "[myhost:123]:src" ssh-bracket-clone-plink-3 && expect_ssh "-v -P 123" myhost src ' -test_expect_success 'single quoted plink.exe is treated specially (as putty) in GIT_SSH_COMMAND' ' +SQ="'" +test_expect_success 'single quoted plink.exe in GIT_SSH_COMMAND' ' copy_ssh_wrapper_as "$TRASH_DIRECTORY/plink.exe" && - GIT_SSH_COMMAND="'"'"'$TRASH_DIRECTORY/plink.exe'"'"' -v" git clone "[myhost:123]:src" ssh-bracket-clone-plink-4 && + GIT_SSH_COMMAND="$SQ$TRASH_DIRECTORY/plink.exe$SQ -v" \ + git clone "[myhost:123]:src" ssh-bracket-clone-plink-4 && expect_ssh "-v -P 123" myhost src '