Feature: make process substitution work when calling Git in Bash (e.g. git diff --no-index <(echo 1) <(echo 2)
)
#4266
Labels
enhancement
Help Wanted
help is requested from collaborators, please!
Potential Project
This issue can be used as a development Project for those loooking for a nice challenge
NOTE: I leave this ticket in its current state for now, as I had started looking into fixing the issue, found out a couple of things, but ultimately could not finish the task in a reasonable amount of time.
Background
In Bash, there is a neat feature where you can use "Process Substitution" to feed programs expecting path parameters some dynamically generated content. For example,
diff
takes two parameters that refer to paths. By using the process substitution construct<(...)
, we can letdiff
compare dynamically generated text:Internally, what Bash does is to replace the parameter with something like
/dev/fd/63
, which is typically a symlink pointing to something like/proc/22962/fd/63
. This works if the called program is an MSYS program, i.e. implicitly aware of the MSYS2 runtime internals. But if it is a MINGW program (likegit.exe
), it is quite puzzled what to do with that Unix path:I've looked into a couple of angles trying to find a way how to fix this.
MSYS2 runtime
The first idea I had was to somehow substitute the parameter with some different path, an NT namespace one (maybe
\\.\pipe\*
), a path that could be opened even by a regular Win32 program. This section describes my findings toward that goal.When opening these paths in an MSYS program and calling
_get_osfhandle()
together with theNtQueryObject()
trick to read a pipe's name, it turns out that they are named pipes with a path like\Device\NamedPipe\29148b3eb257a5c5-45908-pipe-nt-0x141
. This path is generated in the MSYS2 runtime at this location.Now, if it is a named pipe, can't we open it like we do in
simple-ipc
?Apparently not. My attempts failed with
ERROR_PIPE_BUSY
, which indicates that either nobody is listening or that the pipe is opened with incompatible parameters (although I would not understand how the latter could be the case, as the MSYS2 runtime itself performs the same call and it works).Here is some totally undocumented, horribly written quick 'n dirty proof-of-concept that needs to be compiled using
/usr/bin/gcc -g -o a1.exe -Wall a1.c -lntdll && ./a1.exe <(echo hello)
:a1.c
Even calling
WaitNamedPipe()
does not help, it just times out. My best guess is that the MSYS2 runtime somehow "kicks" some other part (e.g. by sending a signal) to start producing the input of said pipe. Or maybe Bash is waiting for a signal before spawning the process?In any case, I've hit what seems like a dead end here, and did not continue to research this angle.
Bash
The source code of Bash does have some code to allow for process substitution to work even without any
/dev/fd/
support: here begins a section of functions that work with Unix-style FIFOs (which are somewhat comparable to Windows Named Pipes).Now, it should be relatively straight-forward to implement another set of functions that use straight-up Win32 named pipes instead of Unix FIFOs, guarded by a certain
#ifdef ... #endif
, and use that in Git Bash.This sounds doable from a first cursory glance but I ran out of time in this spike.
The text was updated successfully, but these errors were encountered: