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

Gitlint hangs on Cygwin #91

Open
jorisroovers opened this issue Jul 5, 2019 · 1 comment
Open

Gitlint hangs on Cygwin #91

jorisroovers opened this issue Jul 5, 2019 · 1 comment
Labels
bug User-facing bugs windows Windows related issues

Comments

@jorisroovers
Copy link
Owner

jorisroovers commented Jul 5, 2019

This also affects 'git bash' which is just Cygwin with a different name.

When using gitlint on Cygwin, it will hang when trying to determine whether there is data being passed via stdin.

# This hangs
gitlint
# Note that Other commands do work, like:
gitlint --version
gitlint generate-config
gitlint install-hook

The issue here is with how Cygwin emulates a shell in windows. In particular, in the testing I've done, stdin is always a named pipe during gitlint invocation.

# Returns True in Cygwin, False everywhere else
python -c "import sys; import os; import stat; print stat.S_ISFIFO(os.fstat(sys.stdin.fileno()).st_mode)"

The issue with this is that once gitlint thinks that stdin is a pipe, it will then attempt and fail to read the stdin(), indefinitely waiting (i.e. gitlint hangs).

The relevant code is here:

gitlint/gitlint/cli.py

Lines 100 to 129 in e95fe61

def get_stdin_data():
""" Helper function that returns data send to stdin or False if nothing is send """
# STDIN can only be 3 different types of things ("modes")
# 1. An interactive terminal device (i.e. a TTY -> sys.stdin.isatty() or stat.S_ISCHR)
# 2. A (named) pipe (stat.S_ISFIFO)
# 3. A regular file (stat.S_ISREG)
# Technically, STDIN can also be other device type like a named unix socket (stat.S_ISSOCK), but we don't
# support that in gitlint (at least not today).
#
# Now, the behavior that we want is the following:
# If someone sends something directly to gitlint via a pipe or a regular file, read it. If not, read from the
# local repository.
# Note that we don't care about whether STDIN is a TTY or not, we only care whether data is via a pipe or regular
# file.
# However, in case STDIN is not a TTY, it HAS to be one of the 2 other things (pipe or regular file), even if
# no-one is actually sending anything to gitlint over them. In this case, we still want to read from the local
# repository.
# To support this use-case (which is common in CI runners such as Jenkins and Gitlab), we need to actually attempt
# to read from STDIN in case it's a pipe or regular file. In case that fails, then we'll fall back to reading
# from the local repo.
mode = os.fstat(sys.stdin.fileno()).st_mode
stdin_is_pipe_or_file = stat.S_ISFIFO(mode) or stat.S_ISREG(mode)
if stdin_is_pipe_or_file:
input_data = sys.stdin.read()
# Only return the input data if there's actually something passed
# i.e. don't consider empty piped data
if input_data:
return ustr(input_data)
return False

The only way to work around this right now is actually pass data to stdin, like so:

git log -1 --pretty="%B" | gitlint

I did a bit of research into this and identified a few potential workarounds that need more investigation:

  1. Detect CYGWIN environment and print a warning message. The only way to reliably detect cygwin seems to try to read the output of the uname command. Python's platform module will NOT consistently report correctly on Cygwin (if python was installed system-wide outside of Cygwin, platform will report Windows and not Cygwin).
  2. Attempt implementing non-blocking reads on windows: https://stackoverflow.com/questions/34504970/non-blocking-read-on-os-pipe-on-windows
  3. Still find a different way to detect that data is not being piped into gitlint, or somehow fix what stat.S_ISFIFO returns by finding/making an environment change in Cygwin.

Some additional pointers that might be relevant:

@jorisroovers jorisroovers added bug User-facing bugs windows Windows related issues labels Jul 5, 2019
jorisroovers added a commit that referenced this issue Jul 8, 2019
Previously, gitlint would still read from stdin and log whatever was passed,
even when the `--ignore-stin` flag was specified. This is problematic for
situations where stdin is blocking and the user is trying to have gitlint ignore
stdin all-together.

This should provide a workaround for #91
@jorisroovers
Copy link
Owner Author

Additional workaround was added with the --ignore-stdin flag in the upcoming v0.12.0 release. Use it like so:

gitlint --ignore-stdin

or in a .gitlint file:

[general]
ignore-stdin=true

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug User-facing bugs windows Windows related issues
Projects
None yet
Development

No branches or pull requests

1 participant