Skip to content

Commit e9d9a8a

Browse files
segevfinergitster
authored andcommitted
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 <[email protected]> Signed-off-by: Johannes Schindelin <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 4e59582 commit e9d9a8a

File tree

2 files changed

+31
-7
lines changed

2 files changed

+31
-7
lines changed

connect.c

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -772,6 +772,7 @@ struct child_process *git_connect(int fd[2], const char *url,
772772
int putty = 0, tortoiseplink = 0;
773773
char *ssh_host = hostandport;
774774
const char *port = NULL;
775+
char *ssh_argv0 = NULL;
775776
transport_check_allowed("ssh");
776777
get_host_and_port(&ssh_host, &port);
777778

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

794795
ssh = get_ssh_command();
795-
if (!ssh) {
796-
const char *base;
797-
char *ssh_dup;
798-
796+
if (ssh) {
797+
char *split_ssh = xstrdup(ssh);
798+
const char **ssh_argv;
799+
800+
if (split_cmdline(split_ssh, &ssh_argv))
801+
ssh_argv0 = xstrdup(ssh_argv[0]);
802+
free(split_ssh);
803+
free((void *)ssh_argv);
804+
} else {
799805
/*
800806
* GIT_SSH is the no-shell version of
801807
* GIT_SSH_COMMAND (and must remain so for
@@ -807,16 +813,19 @@ struct child_process *git_connect(int fd[2], const char *url,
807813
if (!ssh)
808814
ssh = "ssh";
809815

810-
ssh_dup = xstrdup(ssh);
811-
base = basename(ssh_dup);
816+
ssh_argv0 = xstrdup(ssh);
817+
}
818+
819+
if (ssh_argv0) {
820+
const char *base = basename(ssh_argv0);
812821

813822
tortoiseplink = !strcasecmp(base, "tortoiseplink") ||
814823
!strcasecmp(base, "tortoiseplink.exe");
815824
putty = tortoiseplink ||
816825
!strcasecmp(base, "plink") ||
817826
!strcasecmp(base, "plink.exe");
818827

819-
free(ssh_dup);
828+
free(ssh_argv0);
820829
}
821830

822831
argv_array_push(&conn->args, ssh);

t/t5601-clone.sh

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,21 @@ test_expect_success 'tortoiseplink is like putty, with extra arguments' '
386386
expect_ssh "-batch -P 123" myhost src
387387
'
388388

389+
test_expect_success 'double quoted plink.exe in GIT_SSH_COMMAND' '
390+
copy_ssh_wrapper_as "$TRASH_DIRECTORY/plink.exe" &&
391+
GIT_SSH_COMMAND="\"$TRASH_DIRECTORY/plink.exe\" -v" \
392+
git clone "[myhost:123]:src" ssh-bracket-clone-plink-3 &&
393+
expect_ssh "-v -P 123" myhost src
394+
'
395+
396+
SQ="'"
397+
test_expect_success 'single quoted plink.exe in GIT_SSH_COMMAND' '
398+
copy_ssh_wrapper_as "$TRASH_DIRECTORY/plink.exe" &&
399+
GIT_SSH_COMMAND="$SQ$TRASH_DIRECTORY/plink.exe$SQ -v" \
400+
git clone "[myhost:123]:src" ssh-bracket-clone-plink-4 &&
401+
expect_ssh "-v -P 123" myhost src
402+
'
403+
389404
# Reset the GIT_SSH environment variable for clone tests.
390405
setup_ssh_wrapper
391406

0 commit comments

Comments
 (0)