Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Option --path-separator failing on MSys (Git Bash) #537

Closed
fawick opened this issue Feb 20, 2020 · 13 comments · Fixed by #730
Closed

Option --path-separator failing on MSys (Git Bash) #537

fawick opened this issue Feb 20, 2020 · 13 comments · Fixed by #730

Comments

@fawick
Copy link

fawick commented Feb 20, 2020

I have fd 7.4.0 installed on a Windows machine (Rust 1.41.0, stable-x86_64-pc-windows-msvc) and run it from a bash that is provided by Git for Windows, which itself is based on Msys2 (according to https://github.com/git-for-windows/git/wiki/Technical-overview):

$ uname -a
MINGW64_NT-10.0-18363 SOMEHOST 3.0.7-338.x86_64 2019-07-03 15:16 UTC x86_64 Msys

$ fd
bar
bar\baz
bar\baz\bla
bar\baz\bla\some.txt
bar\yetanother.txt
other.txt

fd is using backslashes as it is supposed to do in Windows. #429 added the --path-separator option, which could be useful for using the results as paths within Git Bash. However, in my environment, the option fails, and every backslash is substituted with the absolute path to the Git for Windows installation directory:

$ fd --path-separator="/"
bar
barC:/Program Files/Git/baz
barC:/Program Files/Git/bazC:/Program Files/Git/bla
barC:/Program Files/Git/bazC:/Program Files/Git/blaC:/Program Files/Git/some.txt
barC:/Program Files/Git/yetanother.txt
other.txt

$ ls "C:/Program Files/Git/"
bin/  cmd/  dev/  etc/  git-bash.exe*  git-cmd.exe*  LICENSE.txt  mingw64/  ReleaseNotes.html  tmp/  unins000.dat  unins000.exe*  unins000.msg  usr/

Using single-quotes around the slash character make no difference. Nor does leaving out the quotes all together.

@sharkdp
Copy link
Owner

sharkdp commented Feb 20, 2020

It looks to me like this is a problem of Msys2 or Git Bash. Could you please try these suggestions: https://stackoverflow.com/a/54924640/704831 ?

@fawick
Copy link
Author

fawick commented Feb 25, 2020

Thank you, that was a great hint, @sharkdp! I am very grateful to you for taking the time to dig into this.

For the record, one needs to set the environment variable MSYS_NO_PATHCONV=1:

$ fd --path-separator='/'
bar
barC:/Program Files/Git/baz
barC:/Program Files/Git/bazC:/Program Files/Git/bla
barC:/Program Files/Git/bazC:/Program Files/Git/blaC:/Program Files/Git/some.txt
barC:/Program Files/Git/yetanother.txt
other.txt

$ MSYS_NO_PATHCONV=1 fd --path-separator='/'
bar
bar/baz
bar/baz/bla
bar/baz/bla/some.txt
bar/yetanother.txt
other.txt

@chuxubank
Copy link

chuxubank commented May 31, 2020

This MSYS_NO_PATHCONV=1 fix only works on Git Bash.
When comes to msys2, we should use MSYS2_ARG_CONV_EXCL=--path-separator
Ref: https://www.msys2.org/wiki/Porting/#filesystem-namespaces

@sharkdp
Copy link
Owner

sharkdp commented May 31, 2020

Given that we introduced the --path-separator=… option for situations like Cygwin/MSYS2/Git Bash on Windows, it seems really unfortunate users have to go through this experience described in this ticket.

Maybe we should introduce a --path-separator-slash or --unix-path-separator option as an alias for --path-separator="/", which would not require any environment variables to be set?

What do you think?

@chuxubank
Copy link

Good idea!

@sharkdp
Copy link
Owner

sharkdp commented Jun 6, 2020

Okay, let's turn this into a feature request.

@aswild
Copy link
Contributor

aswild commented Jun 16, 2020

I ran into this today trying to use fd on msys2, and just learned about MSYS2_ARG_CONV_EXCL so maybe I can fix my shell alias.

Could fd go a step further and try to auto-detect the path separator at runtime?

  • MSYS2 sets the MSYSTEM environment variable, which could be checked cheaply
  • Cygwin doesn't seem to set any unique environment variables
    • a hack could be to check for an entry starting with /cygdrive/ in PATH (usually PATH contains /cygdrive/c/Windows/System32, among other native windows path entries) Edit: apparently PATH gets mangled to a Windows-style string C:\foo\bar;C:\baz\quux at runtime, so that won't work.
    • I assume that forking off to a uname process would be too expensive
  • I'm not sure about git bash, except that it's msys/mingw based. Does it also set MSYSTEM?

aswild added a commit to aswild/fd that referenced this issue Jun 17, 2020
Unlike cygwin, msys automatically converts paths, so we don't need
a shell wrapper function to translate things with `cygpath -w`.
Additionally, msys sees --path-separator=/ and turns the / into "C:\",
which is even worse.

Hack around this by checking the $MSYSTEM environment variable and
automatically setting the path separator accordingly.

See sharkdp#537
@sharkdp
Copy link
Owner

sharkdp commented Jun 17, 2020

@aswild Great idea. Maybe this could help for cygwin: https://stackoverflow.com/a/3104453 ?

@aswild
Copy link
Contributor

aswild commented Jun 17, 2020

Ooh, OSTYPE looks so promising but apparently it's only set as a shell variable and isn't exported to the environment, foiled again.

@sharkdp
Copy link
Owner

sharkdp commented Dec 6, 2020

It would be great if someone could summarize the current status and what should/could be done here to improve the situation.

@chuxubank
Copy link

I haven't used msys2 for a while. Instead, I'm using WSL now and no longer need this option.

I think it's OK to leave it unchanged since I already give the workaround in msys2 at #537 (comment)

@aswild
Copy link
Contributor

aswild commented Jan 10, 2021

It would be great if someone could summarize the current status and what should/could be done here to improve the situation.

My current view of the world:

  • On MSYS (including all 3 flavors of MSYS2 shell and Git Bash), the MSYSTEM environment variable is exported, and programs can use that to detect an MSYS/MinGW shell. This is what I did on my fork in aswild@4441615
  • You can globally disable MSYS' automatic path replacement (e.g. turning / into C:\msys64) by setting MSYS_NO_PATHCONV or MSYS2_ARG_CONV_EXCL, but you can also just write a double slash to disable it for a single argument, e.g. fd --path-separator=// ... (when fd executes, it will only see a single /)
  • Cygwin is a mess on Rust in general
    • Cygwin is a unique environment that simultaneously both Unix and Windows. It works for C code because of the special Cygwin libc that hooks into all the low-level functions that would be syscalls on Linux.
    • Rust itself doesn't know about this (I see libstd contains some "raw" syscalls implemented in Rust rather than calling libc), and I think things go all the way back to missing LLVM support.
    • You can set the right environment variables to use rustup (x86_64-pc-windows-gnu) inside of Cygwin, but I've never been able to build anything that requires calling out to GCC or other external libraries, only pure-rust crates. I tried and failed attempting to get rustup to even find a MinGW version of GCC from within Cygwin.
  • There's no sane way to detect Cygwin at runtime (without custom user-set environment variables) that I know of.
    • Cygwin doesn't do automatic path conversion like MSYS, because it expects that you'll be running Cygwin-compiled programs which understand its Unix-like filesystem internally (which native Win32 programs, including anything Rust, do not)
    • Thus, to use any Rust program from Cygwin, it must be compiled in a MinGW environment, and you need some sort of wrapper function to call cygpath -w on anything that looks like an absolute path. For example, here's what I did for fd: https://github.com/aswild/linuxfiles/blob/master/myshrc#L719
  • WSL is great and gaining in popularity, so I bet that the Cygwin issues inherent to Rust may never get fixed - anyone deep enough in Rust internals to fix them probably has better things to spend their time on

What could fd do?

  • @sharkdp if you like it, feel free to cherry-pick or adapt aswild@4441615 (or I can turn it into a PR). I think this fixes the common use case of fd in MSYS(2)/Git Bash and doesn't require users to learn about the PATHCONV/ARG_CONV environment variables or set shell aliases/functions.
  • Acknowledge/document that Rust is inherently limited in Cygwin for reasons that Rust programs can't control or cleanly work around on their own.

@sharkdp
Copy link
Owner

sharkdp commented Feb 13, 2021

@sharkdp if you like it, feel free to cherry-pick or adapt aswild@4441615 (or I can turn it into a PR). I think this fixes the common use case of fd in MSYS(2)/Git Bash and doesn't require users to learn about the PATHCONV/ARG_CONV environment variables or set shell aliases/functions.

A PR would be very much appreciated - thank you!

aswild added a commit to aswild/fd that referenced this issue Feb 14, 2021
MSYS and MSYS2 environments (such as Git Bash) have a UNIX like
filesystem which uses '/' as the path separator rather than '\', but
Rust doesn't know about this by default.

On Windows, check the MSYSTEM environment variable and set the default
value of the --path-separator option to '/' for convenience.

There is no similar detection of Cygwin because there seems to be no way
for Rust (and any native Win32) programs to detect that they're being
called from a Cygwin environment. Cygwin users can use a shell
alias/function/script to wrap fd.

Fixes: sharkdp#537
aswild added a commit to aswild/fd that referenced this issue Feb 14, 2021
MSYS and MSYS2 environments (such as Git Bash) have a UNIX like
filesystem which uses '/' as the path separator rather than '\', but
Rust doesn't know about this by default.

On Windows, check the MSYSTEM environment variable and set the default
value of the --path-separator option to '/' for convenience.

There is no similar detection of Cygwin because there seems to be no way
for Rust (and any native Win32) programs to detect that they're being
called from a Cygwin environment. Cygwin users can use a shell
alias/function/script to wrap fd.

Fixes: sharkdp#537
aswild added a commit to aswild/fd that referenced this issue Feb 15, 2021
MSYS and MSYS2 environments (such as Git Bash) have a UNIX like
filesystem which uses '/' as the path separator rather than '\', but
Rust doesn't know about this by default.

On Windows, check the MSYSTEM environment variable and set the default
value of the --path-separator option to '/' for convenience.

There is no similar detection of Cygwin because there seems to be no way
for Rust (and any native Win32) programs to detect that they're being
called from a Cygwin environment. Cygwin users can use a shell
alias/function/script to wrap fd.

Fixes: sharkdp#537
sharkdp pushed a commit that referenced this issue Feb 15, 2021
MSYS and MSYS2 environments (such as Git Bash) have a UNIX like
filesystem which uses '/' as the path separator rather than '\', but
Rust doesn't know about this by default.

On Windows, check the MSYSTEM environment variable and set the default
value of the --path-separator option to '/' for convenience.

There is no similar detection of Cygwin because there seems to be no way
for Rust (and any native Win32) programs to detect that they're being
called from a Cygwin environment. Cygwin users can use a shell
alias/function/script to wrap fd.

Fixes: #537
@sharkdp sharkdp added this to the fd 9.x milestone Aug 9, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants