-
Notifications
You must be signed in to change notification settings - Fork 220
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
lefthook can swallow stdin from user typing at the terminal unexpectedly #588
Comments
I have this issue too! |
I also have this issue! |
Even with no_tty: true
skip_output:
- meta # Skips lefthook version printing
- summary # Skips summary block (successful and failed steps) printing
- empty_summary # Skips summary heading when there are no steps to run
- success # Skips successful steps printing
- failure # Skips failed steps printing
- execution # Skips printing any execution logs (but prints if the execution failed)
- execution_out # Skips printing execution output (but still prints failed commands output)
- execution_info # Skips printing `EXECUTE > ...` logging
- skips # Skips "skip" printing (i.e. no files matched)
- meta # Skips lefthook version printing
post-checkout:
commands:
sleep:
run: sleep 2 $ git checkout
M lefthook.yml
Your branch is up to date with 'origin/main'.
asdf asdf asdf asdf%
$ sdf asdf asdf |
Hey! Thank you for reporting this issue. There are cases when lefthook expects something from STDIN. This is controlled by |
I've tried to reproduce this issue, but couldn't do that. The example config: pre-commit:
commands:
sleep:
run: sleep 2 I am not sure what the problem is. I use lefthook version 1.5.3, zsh 5.9. Could you please try ❯ git commit -m 'test'
[sleep called from hook script]
1234[sleep done]
5╭──────────────────────────────────────╮
│ 🥊 lefthook v1.5.3 hook: pre-commit │
╰──────────────────────────────────────╯
sync hooks: ✔️ (pre-commit)
6┃ sleep ❯
789
────────────────────────────────────
summary: (done in 2.50 seconds)
✔️ sleep
[main 3c7c0c1] test
1 file changed, 1 insertion(+)
e
lh-test git:main 6s
❯ 123456789 |
I use fish on macOS in iTerm2. I've tested against zsh and bash, and get the same result. Interestingly, I tried making a script to reproduce, but it does not reproduce: #!/usr/bin/env bash
echo "# noise" >> lefthook.yml
printf "git commit -a -m 'test'\necho hello world" | bash Might be having to do with it being one command and multiple lines, but I'll keep experimenting.
Sure, here you go!
|
I was able to reproduce stdin not being swallowed when using a plain #!/usr/bin/env bash
echo "[sleep from $0]"
sleep 2 CleanShot.2023-11-29.at.09.31.52.mp4Something I was wondering is, would it be possible to defer opening/attaching stdin until something explicitly uses it? ie |
@technicalpickles , so stdin still gets swallowed even if you run lefthook from the console? Like |
Oh, I see. It looks like you type I'll try to fix this, but it feels like a complicated thing, since lefthook doesn't know about stdin usage until config is parsed and a command is being run. |
Right, the use case here is, I have a bunch of things I want to accomplish, and the first one is slow. So I type in all of the commands and then go focus on something else. And I am hoping to come back later, seeing that all of the commands I typed in are ones that ran or at least were attempted. |
The fix will be soon released in version 1.5.5 |
That's right, it includes hitting I tried out 1.5.5, and still see the same behavior 🤔 My current test file: pre-commit:
follow: true
commands:
sleep:
interactive: false
use_stdin: false
run: sleep 2 I'm still working on an automated reproduction. Thinking to try something like |
Ok, I could reproduce this with iTerm2. Usually I use I will need some extra time to dig into this. But It feels like to fix this I need to close STDIN before running any command, and this is usually not a good idea, and many things could stop working. But I'll come back later after some testing. |
Oh! That makes a lot of sense that tmux would affect it. Do you mind re-opening while its still happening?
That was my thought too originally. I'm not actually sure what the default behavior is re-stdin. I can't think of times I've had to explicitly close it, for example, just open it when its needed. For example, consider this bash script: echo "so sleepy"
sleep 5
echo "huh what did I miss" You can see this doesn't do anything with stdin, and it also doesn't capture the stdin if you type it while it's running. I looked at our previous tool we've been comparing too (committer) and it doesn't do anything specific to stdin. Do you think one of the libraries we're using could be doing something? |
Similarly, this go script doesn't capture input: package main
import (
"fmt"
"time"
)
func main() {
fmt.Println("So sleepy")
time.Sleep(5 * time.Second)
fmt.Println("huh what did I miss")
} |
FWIW I use |
I think I've tracked down where the input gets swallowed:
In slightly larger context, this is in conditional logic when the command is NOT (interactive OR using stdin). If that is the case, I don't think we need to be doing that. If we aren't using stdin, then why do we need the input? lefthook/internal/lefthook/run/exec/execute_unix.go Lines 89 to 108 in 1af059d
I tested by commenting the offending line out, and building with I've been looking at the code in I'll push up a PR to see how tests look in any event. |
…ve and not using stdin If I'm reading the code, this `args.in` should be a nullReader when non-interactive and not using stdin. For some reason though, it ends up capturing stdin. That is, any typing you do while lefthook is running goes to lefthook, instead of the shell invoking it. Fixes evilmartians#588
If I'm reading the code, this `args.in` should be a nullReader when non-interactive and not using stdin. For some reason though, it ends up capturing stdin. That is, any typing you do while lefthook is running goes to lefthook, instead of the shell invoking it. Fixes #588
When I was testing #638 I was only testing in the test repo I had, not our main repo. I was testing in our main repo, and it seems there is still some window that stdin is still captured 😢 It definitely is a smaller window though! Specifically, sometimes it's capturing only The easiest way to reproduce (but not to share) on a bigish repo is:
If you It's worth noting this is specifically a post-checkout or post-merge hook. My other tests were pre-commit. |
Interestingly, I see the behavior during |
Paired for a bit with @ngan, and did a bunch of bisecting... that is, commenting out code to see what causes and what doesn't cause it 😂 We managed to trace it down to: Line 42 in 0845abb
lefthook/internal/lefthook/run.go Line 35 in 0845abb
lefthook/internal/lefthook/lefthook.go Line 53 in 0845abb
lefthook/internal/git/repository.go Line 51 in 0845abb
That is to say, as soon as lefthook tries to call |
This is going to sound crazy, but I traced it further down to Line 33 in 0845abb
Line 54 in 0845abb
stdin is not captured when all the Diving another layer into the logger... Line 106 in 0845abb
Commenting out this line, stdin is not swallowed. changing it to Lines 310 to 315 in 0845abb
Taken together, it seems there is a problem down in |
Wooow, that's a huge catch! I will release the fix ASAP |
Thank you, it was a wild one. I'd like to take a nap for the rest of the week if that's alright. To summarize from the PRs, upgrading lipgloss seemed to fix the problem in #649 . It's not an official release, but I also noticed it was updating uniseg from 0.2.0 to 0.4.6. On a hunch, I tried upgrading just that, and it worked 🙃 And thank for merging & releasing #650 🎊 ❤️ 🎊 |
🔧 Summary
consider a workflow like this:
Out of muscle memory, it's really easy to hit enter, and immediately start typing the next command while the first command is still running. It seems that lefthook ends up receiving that command you start typing though, so when the first command is finished, the input with the second command doesn't get to the shell.
For some additional context, I've gotten this complaint from a few people after migrating from committer to lefthook.
Lefthook version
1.5.2
Steps to reproduce
lefthook.yaml
:git commit -a -m "test"<enter>
git checkout main<enter>
Expected results
shell receives the input for the next command, ie
git checkout main<enter>
Actual results
input with second command,
git checkout main
, isn't received by the shell.Possible Solution
I think it should be possible to close stdin, so it doesn't receive any of the input from a user. I don't know if there are any cases where lefthook does read from stdin though.
Logs / Screenshots
CleanShot.2023-11-27.at.13.47.34.mp4
The text was updated successfully, but these errors were encountered: