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

[PATCH v2 0/3] Handle PuTTY (plink/tortoiseplink) even in GIT_SSH_COMMAND

From
Johannes Schindelin <johannes.schindelin@gmx.de>
Date
Jan 26, 2017, 14:51 UTC
Message-ID
<alpine.DEB.2.20.1701261550590.3469@virtualbox>
In-Reply-To
<2ff29a4d00e0e13d460122d8008e762361ca90aa.1483358673.git.johannes.schindelin@gmx.de>

We already handle PuTTY's plink and TortoiseGit's tortoiseplink in GIT_SSH by automatically using the -P option to specify ports, and in tortoiseplink's case by passing the --batch option.

For users who need to pass additional command-line options to plink, this poses a problem: the only way to do that is to use GIT_SSH_COMMAND, but Git does not handle that specifically, so those users have to manually parse the command-line options passed via GIT_SSH_COMMAND and replace -p (if present) by -P, and add --batch in the case of tortoiseplink.

This is error-prone and a bad user experience.

To fix this, the changes proposed in this patch series introduce handling this by splitting the GIT_SSH_COMMAND value and treating the first parameter with the same grace as GIT_SSH. To counter any possible misdetection, the user can also specify explicitly via GIT_SSH_VARIANT or ssh.variant which SSH variant they are using.

This is v2 of the patch, now turned patch series. Relative to v1, it integrates Junio's cleanup patch and Segev's follow-up Pull Request that introduces the GIT_SSH_VARIANT and ssh.variant settings to override Git's autodetection manually.

Junio C Hamano (1):
  connect: rename tortoiseplink and putty variables
Segev Finer (2):
  connect: handle putty/plink also in GIT_SSH_COMMAND
  connect: Add the envvar GIT_SSH_VARIANT and ssh.variant config
 Documentation/config.txt |  7 +++++
 Documentation/git.txt    |  7 +++++
 connect.c                | 66 +++++++++++++++++++++++++++++++++++-------------
 t/t5601-clone.sh         | 41 ++++++++++++++++++++++++++++++
 4 files changed, 104 insertions(+), 17 deletions(-)
base-commit: 4e59582ff70d299f5a88449891e78d15b4b3fabe
Published-As: https://github.com/dscho/git/releases/tag/putty-w-args-v2
Fetch-It-Via: git fetch https://github.com/dscho/git putty-w-args-v2
Interdiff vs v1:
 diff --git a/Documentation/config.txt b/Documentation/config.txt
 index af2ae4cc02..f2c210f0a0 100644
 --- a/Documentation/config.txt
 +++ b/Documentation/config.txt
 @@ -1949,6 +1949,13 @@ Environment variable settings always override any matches.  The URLs that are
  matched against are those given directly to Git commands.  This means any URLs
  visited as a result of a redirection do not participate in matching.
  
 +ssh.variant::
 +	Override the autodetection of plink/tortoiseplink in the SSH
 +	command that 'git fetch' and 'git push' use. It can be set to
 +	either `ssh`, `plink`, `putty` or `tortoiseplink`. Any other
 +	value will be treated as normal ssh. This is useful in case
 +	that Git gets this wrong.
 +
  i18n.commitEncoding::
  	Character encoding the commit messages are stored in; Git itself
  	does not care per se, but this information is necessary e.g. when
 diff --git a/Documentation/git.txt b/Documentation/git.txt
 index 4f208fab92..c322558aa7 100644
 --- a/Documentation/git.txt
 +++ b/Documentation/git.txt
 @@ -1020,6 +1020,13 @@ Usually it is easier to configure any desired options through your
  personal `.ssh/config` file.  Please consult your ssh documentation
  for further details.
  
 +`GIT_SSH_VARIANT`::
 +	If this environment variable is set, it overrides the autodetection
 +	of plink/tortoiseplink in the SSH command that 'git fetch' and 'git
 +	push' use. It can be set to either `ssh`, `plink`, `putty` or
 +	`tortoiseplink`. Any other value will be treated as normal ssh. This
 +	is useful in case that Git gets this wrong.
 +
  `GIT_ASKPASS`::
  	If this environment variable is set, then Git commands which need to
  	acquire passwords or passphrases (e.g. for HTTP or IMAP authentication)
 diff --git a/connect.c b/connect.c
 index c81f77001b..7b4437578b 100644
 --- a/connect.c
 +++ b/connect.c
 @@ -691,6 +691,24 @@ static const char *get_ssh_command(void)
  	return NULL;
  }
  
 +static int handle_ssh_variant(int *port_option, int *needs_batch)
 +{
 +	const char *variant;
 +
 +	if (!(variant = getenv("GIT_SSH_VARIANT")) &&
 +		git_config_get_string_const("ssh.variant", &variant))
 +		return 0;
 +
 +	if (!strcmp(variant, "plink") || !strcmp(variant, "putty"))
 +		*port_option = 'P';
 +	else if (!strcmp(variant, "tortoiseplink")) {
 +		*port_option = 'P';
 +		*needs_batch = 1;
 +	}
 +
 +	return 1;
 +}
 +
  /*
   * This returns a dummy child_process if the transport protocol does not
   * need fork(2), or a struct child_process object if it does.  Once done,
 @@ -769,7 +787,8 @@ struct child_process *git_connect(int fd[2], const char *url,
  		conn->in = conn->out = -1;
  		if (protocol == PROTO_SSH) {
  			const char *ssh;
 -			int putty = 0, tortoiseplink = 0;
 +			int needs_batch = 0;
 +			int port_option = 'p';
  			char *ssh_host = hostandport;
  			const char *port = NULL;
  			char *ssh_argv0 = NULL;
 @@ -816,28 +835,32 @@ struct child_process *git_connect(int fd[2], const char *url,
  				ssh_argv0 = xstrdup(ssh);
  			}
  
 -			if (ssh_argv0) {
 +			if (!handle_ssh_variant(&port_option, &needs_batch) &&
 +			    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_argv0);
 +				if (!strcasecmp(base, "tortoiseplink") ||
 +				    !strcasecmp(base, "tortoiseplink.exe")) {
 +					port_option = 'P';
 +					needs_batch = 1;
 +				} else if (!strcasecmp(base, "plink") ||
 +					   !strcasecmp(base, "plink.exe")) {
 +					port_option = 'P';
 +				}
  			}
  
 +			free(ssh_argv0);
 +
  			argv_array_push(&conn->args, ssh);
  			if (flags & CONNECT_IPV4)
  				argv_array_push(&conn->args, "-4");
  			else if (flags & CONNECT_IPV6)
  				argv_array_push(&conn->args, "-6");
 -			if (tortoiseplink)
 +			if (needs_batch)
  				argv_array_push(&conn->args, "-batch");
  			if (port) {
 -				/* P is for PuTTY, p is for OpenSSH */
 -				argv_array_push(&conn->args, putty ? "-P" : "-p");
 +				argv_array_pushf(&conn->args,
 +						 "-%c", port_option);
  				argv_array_push(&conn->args, port);
  			}
  			argv_array_push(&conn->args, ssh_host);
 diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh
 index 9335e10c2a..b52b8acf98 100755
 --- a/t/t5601-clone.sh
 +++ b/t/t5601-clone.sh
 @@ -401,6 +401,32 @@ test_expect_success 'single quoted plink.exe in GIT_SSH_COMMAND' '
  	expect_ssh "-v -P 123" myhost src
  '
  
 +test_expect_success 'GIT_SSH_VARIANT overrides plink detection' '
 +	copy_ssh_wrapper_as "$TRASH_DIRECTORY/plink" &&
 +	GIT_SSH_VARIANT=ssh \
 +	git clone "[myhost:123]:src" ssh-bracket-clone-variant-1 &&
 +	expect_ssh "-p 123" myhost src
 +'
 +
 +test_expect_success 'ssh.variant overrides plink detection' '
 +	copy_ssh_wrapper_as "$TRASH_DIRECTORY/plink" &&
 +	git -c ssh.variant=ssh \
 +		clone "[myhost:123]:src" ssh-bracket-clone-variant-2 &&
 +	expect_ssh "-p 123" myhost src
 +'
 +
 +test_expect_success 'GIT_SSH_VARIANT overrides plink detection to plink' '
 +	GIT_SSH_VARIANT=plink \
 +	git clone "[myhost:123]:src" ssh-bracket-clone-variant-3 &&
 +	expect_ssh "-P 123" myhost src
 +'
 +
 +test_expect_success 'GIT_SSH_VARIANT overrides plink to tortoiseplink' '
 +	GIT_SSH_VARIANT=tortoiseplink \
 +	git clone "[myhost:123]:src" ssh-bracket-clone-variant-4 &&
 +	expect_ssh "-batch -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 15 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.