Skip to content

Commit

Permalink
connect: handle putty/plink also in GIT_SSH_COMMAND
Browse files Browse the repository at this point in the history
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 <segev208@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
segevfiner authored and gitster committed Jan 25, 2017
1 parent 4e59582 commit e9d9a8a
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 7 deletions.
23 changes: 16 additions & 7 deletions connect.c
Expand Up @@ -772,6 +772,7 @@ struct child_process *git_connect(int fd[2], const char *url,
int putty = 0, tortoiseplink = 0;
char *ssh_host = hostandport;
const char *port = NULL;
char *ssh_argv0 = NULL;
transport_check_allowed("ssh");
get_host_and_port(&ssh_host, &port);

Expand All @@ -792,10 +793,15 @@ struct child_process *git_connect(int fd[2], const char *url,
}

ssh = get_ssh_command();
if (!ssh) {
const char *base;
char *ssh_dup;

if (ssh) {
char *split_ssh = xstrdup(ssh);
const char **ssh_argv;

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
* GIT_SSH_COMMAND (and must remain so for
Expand All @@ -807,16 +813,19 @@ struct child_process *git_connect(int fd[2], const char *url,
if (!ssh)
ssh = "ssh";

ssh_dup = xstrdup(ssh);
base = basename(ssh_dup);
ssh_argv0 = xstrdup(ssh);
}

if (ssh_argv0) {
const char *base = basename(ssh_argv0);

tortoiseplink = !strcasecmp(base, "tortoiseplink") ||
!strcasecmp(base, "tortoiseplink.exe");
putty = tortoiseplink ||
!strcasecmp(base, "plink") ||
!strcasecmp(base, "plink.exe");

free(ssh_dup);
free(ssh_argv0);
}

argv_array_push(&conn->args, ssh);
Expand Down
15 changes: 15 additions & 0 deletions t/t5601-clone.sh
Expand Up @@ -386,6 +386,21 @@ test_expect_success 'tortoiseplink is like putty, with extra arguments' '
expect_ssh "-batch -P 123" myhost src
'

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 &&
expect_ssh "-v -P 123" myhost src
'

SQ="'"
test_expect_success 'single quoted plink.exe in GIT_SSH_COMMAND' '
copy_ssh_wrapper_as "$TRASH_DIRECTORY/plink.exe" &&
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
'

# Reset the GIT_SSH environment variable for clone tests.
setup_ssh_wrapper

Expand Down

0 comments on commit e9d9a8a

Please sign in to comment.