Escaping core.askpass

320 views
Skip to first unread message

dmitry....@gmail.com

unread,
Sep 23, 2013, 7:24:57 AM9/23/13
to msy...@googlegroups.com
Hi,

how do I escape spaces in core.askpass passed as a -c option like this:

git -c core.askpass="path with whitespaces" fetch origin

I've tried all sorts of things like closing path inside single quotes or escaping whitespaces with \ or ^, but non of them work... What the right way to do escaping?

Konstantin Khomoutov

unread,
Sep 23, 2013, 8:31:16 AM9/23/13
to dmitry....@gmail.com, msy...@googlegroups.com
I reckon the answers is "it depends".

A short dive into the sources indicates Git on Windows uses
mingw_spawnpe() function to run the program obtained from the
core.askpass configuration variable, and on POSIX platforms, fork() +
exec() are used. While I failed to google the actual code of
mingw_spawnpe(), I'm certain it eventually calls CreateProcess().
Both these facts hint at that the program is executed directly, not via
the shell. This, in turn, means there will be no second round of
shell substitutions performed on its pathname.

Now the problem is that you did not tell us which environment your
`git` command runs in: Windows shell (cmd.exe) and Git Bash (bash.exe)
have different rules for quoting and escaping. I'm not sure about
PowerShell you might be using as I'm not familiar with it.

Another problem could be with slashes (forward vs backward) thought I
think Win32 API should have no problem running a program with forward
slashes (or even a mixture of both) in its pathname.

Anyway, what I'd try to do is to enable tracing before running your
command by making sure it sees the "GIT_TRACE" variable in the
environment, set to something like "1" -- this would print out exactly
how your command looks just before it's attempted to be run, so you
could do some debugging.

To do some guesswork, I'd say if you're using Git Bash, any of the
calls would work:

git -c core.askpass=/c/a/path\ with\ spaces/program ...
git -c core.askpass='/c/a/path with spaces/program' ...
git -c core.askpass="/c/a/path with spaces/program" ...
git -c core.askpass='c:\a\path with spaces\program' ...
git -c "core.askpass=/c/a/path with spaces/program" ...
git -c 'core.askpass=c:\a\path with spaces\program' ...

For Windows shell I'd escape the whole argument to '-c' as presented in
the two last examples above, and note that Windows shell does not treat
a single quote character in any special manner, so

git -c "core.askpass=/c/a/path with spaces/program" ...
git -c "core.askpass=c:/a/path with spaces/program" ...
git -c "core.askpass=c:\a\path with spaces\program" ...

Johannes Schindelin

unread,
Sep 23, 2013, 1:12:58 PM9/23/13
to Konstantin Khomoutov, dmitry....@gmail.com, msy...@googlegroups.com
Hi,

On Mon, 23 Sep 2013, Konstantin Khomoutov wrote:

> While I failed to google the actual code of mingw_spawnpe(),

While Google used to be excellent at finding code, it sucks in the
meantime at that job. Much better to use GitHub directly. For your
convenience:

https://github.com/msysgit/git/blob/master/compat/mingw.c#L1221

Ciao,
Dscho

Dmitry Neverov

unread,
Sep 23, 2013, 1:19:24 PM9/23/13
to Konstantin Khomoutov, msy...@googlegroups.com
I'm trying to run it from windows console. I've tried all the
suggestions you gave but with no success. A typical output with
GIT_TRACE=1 is the following:

C:\some_path>git -c core.askpass="C:\dir with space\pass.bat" fetch --progress origin +refs/heads/master:refs/remotes/origin/master
trace: built-in: git 'fetch' '--progress' 'origin' '+refs/heads/master:refs/remotes/origin/master'
trace: run_command: 'git-remote-https' 'origin' 'https://m...@acme.com/repo.git'
trace: run_command: 'C:\dir with space\pass.bat' 'Password for '\''https://m...@acme.com'\'': '
'C:\dir' is not recognized as an internal or external command,
operable program or batch file.
error: unable to read askpass response from 'C:\dir with space\pass.bat'
Password for 'https://m...@acme.com':
fatal: Authentication failed

Did you mean git uses mingw_spawnvpe? I've found it's sources in
compat/mingw.c. It calls mingw_spawnve_fd which in turn indeed
calls CreateProcess. CreateProcess
states that application name with spaces should be quoted, but it
seems like mingw_spawnve_fd doesn't quote its cmd argument.

Also I've tried to add quotes myself it also didn't help:

C:\some_paht>git -c core.askpass="\"c:\dir with space\pass.bat\"" fetch --progress origin +refs/heads/master:refs/remotes/origin/master
trace: built-in: git 'fetch' '--progress' 'origin' '+refs/heads/master:refs/remotes/origin/master'
trace: run_command: 'git-remote-https' 'origin' 'https://m...@acme.com/repo.git'
trace: run_command: '"c:\dir with space\pass.bat"' 'Password for '\''https://m...@acme.com'\'': '
error: cannot spawn "c:\dir with space\pass.bat": No such file or directory
Password for 'https://m...@acme.com':
fatal: Authentication failed

Johannes Schindelin

unread,
Sep 23, 2013, 1:41:46 PM9/23/13
to Dmitry Neverov, Konstantin Khomoutov, msy...@googlegroups.com
Hi Dmitry,

On Mon, 23 Sep 2013, Dmitry Neverov wrote:

> C:\some_paht>git -c core.askpass="\"c:\dir with space\pass.bat\"" fetch
> --progress origin +refs/heads/master:refs/remotes/origin/master

Almost...

> error: cannot spawn "c:\dir with space\pass.bat": No such file or directory

Batch files cannot be executed directly. They have to be executed via cmd
(cmd /c \"...\" IIRC).

Ciao,
Johannes

Dmitry Neverov

unread,
Sep 23, 2013, 1:53:23 PM9/23/13
to Johannes Schindelin, msy...@googlegroups.com
I wonder why it works fine when pass.bat is in dir without
spaces? How do I ask git to launch my pass.bat with "cmd.exe /c"?
I've noticed that it parses interpreter in the script so I've
added

#!cmd.exe /c

to the top of my pass.bat, but still get the error:

cannot spawn "c:\dir with space\pass.bat": No such file or directory

Johannes Schindelin

unread,
Sep 23, 2013, 2:47:22 PM9/23/13
to Dmitry Neverov, msy...@googlegroups.com
Hi Dmitry,

On Mon, 23 Sep 2013, Dmitry Neverov wrote:

> I wonder why it works fine when pass.bat is in dir without
> spaces?

I guess that it is some special handling in the Win32 API, but frankly, I
don't know.

> How do I ask git to launch my pass.bat with "cmd.exe /c"?

By specifying it in the command-line as before: just prefix the
(escape-quoted) path with "cmd.exe /c":

C:\some_path> git -c core.askpass="cmd /c \"c:\dir with space\pass.bat\"" fetch --progress origin +refs/heads/master:refs/remotes/origin/master

or some variation on it.

> I've noticed that it parses interpreter in the script so I've
> added
>
> #!cmd.exe /c
>
> to the top of my pass.bat, but still get the error:
>
> cannot spawn "c:\dir with space\pass.bat": No such file or directory

I *think* the shebang line requires an absolute path to the executable.
You will only find out for sure by debugging from the source, though.

Ciao,
Johannes

Dmitry Neverov

unread,
Sep 23, 2013, 11:48:12 PM9/23/13
to Johannes Schindelin, msy...@googlegroups.com
Unfortunately, neither specifying a full path as interpreter nor using 
-c core.askpass="cmd /c \"c:\dir with space\pass.bat\"" helps, I still
get the same error.
Reply all
Reply to author
Forward
0 new messages