git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v2 1/3] connect: handle putty/plink also in GIT_SSH_COMMAND

From
Johannes Schindelin <johannes.schindelin@gmx.de>
Date
Jan 26, 2017, 14:51 UTC
Message-ID
<199723aedcaa8464967a9faf33163c0cd196c941.1485442231.git.johannes.schindelin@gmx.de>
In-Reply-To
<cover.1485442231.git.johannes.schindelin@gmx.de>
From: Segev Finer <segev208@gmail.com>

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>
---
 connect.c        | 23 ++++++++++++++++-------
 t/t5601-clone.sh | 15 +++++++++++++++
 2 files changed, 31 insertions(+), 7 deletions(-)
diff --git a/connect.c b/connect.c
index 8cb93b0720..c81f77001b 100644
--- a/connect.c
+++ b/connect.c
@@ -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);
 
@@ -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
@@ -807,8 +813,11 @@ 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");
@@ -816,7 +825,7 @@ struct child_process *git_connect(int fd[2], const char *url,
 					!strcasecmp(base, "plink") ||
 					!strcasecmp(base, "plink.exe");
 
-				free(ssh_dup);
+				free(ssh_argv0);
 			}
 
 			argv_array_push(&conn->args, ssh);
diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh
index 4241ea5b32..9335e10c2a 100755
--- a/t/t5601-clone.sh
+++ b/t/t5601-clone.sh
@@ -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
 
-- 
2.11.1.windows.prerelease.2.9.g3014b57
Previous: Johannes SchindelinNext: Johannes Schindelin
Message 16 of 38 in “connect: handle putty/plink also in GIT_SSH_COMMAND”
  1. connect: handle putty/plink also in GIT_SSH_COMMANDJohannes Schindelin, Jan 2, 2017
  2. Junio C HamanoJan 8, 2017
  3. Junio C HamanoJan 9, 2017
  4. Johannes SchindelinJan 9, 2017
  5. Junio C HamanoJan 9, 2017
  6. Johannes SchindelinJan 9, 2017
  7. Junio C HamanoJan 9, 2017
  8. Johannes SchindelinJan 25, 2017
  9. Junio C HamanoJan 25, 2017
  10. Junio C HamanoJan 25, 2017
  11. Johannes SchindelinJan 26, 2017
  12. Jeff KingJan 25, 2017
  13. Junio C HamanoJan 25, 2017
  14. Johannes SchindelinJan 26, 2017
  15. 0/3 Handle PuTTY (plink/tortoiseplink) even in GIT_SSH_COMMANDJohannes Schindelin, Jan 26, 2017
  16. 1/3 connect: handle putty/plink also in GIT_SSH_COMMANDJohannes Schindelin, Jan 26, 2017
  17. 2/3 connect: rename tortoiseplink and putty variablesJohannes Schindelin, Jan 26, 2017
  18. 3/3 connect: Add the envvar GIT_SSH_VARIANT and ssh.variant configJohannes Schindelin, Jan 26, 2017
  19. Junio C HamanoJan 26, 2017
  20. Johannes SchindelinJan 27, 2017
  21. Junio C HamanoJan 27, 2017
  22. Johannes SchindelinFeb 1, 2017
  23. Junio C HamanoFeb 1, 2017
  24. 0/4 Handle PuTTY (plink/tortoiseplink) even in GIT_SSH_COMMANDJohannes Schindelin, Feb 1, 2017
  25. 1/4 connect: handle putty/plink also in GIT_SSH_COMMANDJohannes Schindelin, Feb 1, 2017
  26. 2/4 connect: rename tortoiseplink and putty variablesJohannes Schindelin, Feb 1, 2017
  27. 3/4 git_connect(): factor out SSH variant handlingJohannes Schindelin, Feb 1, 2017
  28. 4/4 connect: Add the envvar GIT_SSH_VARIANT and ssh.variant configJohannes Schindelin, Feb 1, 2017
  29. Junio C HamanoFeb 1, 2017
  30. Junio C HamanoFeb 1, 2017
  31. Johannes SchindelinFeb 1, 2017
  32. Junio C HamanoFeb 1, 2017
  33. Johannes SchindelinFeb 1, 2017
  34. Junio C HamanoFeb 1, 2017
  35. Johannes SchindelinFeb 1, 2017
  36. Junio C HamanoFeb 1, 2017
  37. Johannes SchindelinFeb 1, 2017
  38. Junio C HamanoFeb 1, 2017

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.