Skip to content

Pre-commit hooks are executed only when launched from the git root #2281

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

Closed
savchenko opened this issue Jun 28, 2024 · 16 comments · Fixed by #2571
Closed

Pre-commit hooks are executed only when launched from the git root #2281

savchenko opened this issue Jun 28, 2024 · 16 comments · Fixed by #2571
Assignees
Labels
bug Something isn't working
Milestone

Comments

@savchenko
Copy link

savchenko commented Jun 28, 2024

Describe the bug
Pre-commit hook is ignored.

To Reproduce
Steps to reproduce the behavior:

  1. mkdir .githooks && git config --local core.hooksPath .githooks
  2. Create .githooks/pre-commit with echo "Hook triggered" && exit 1 and chmod +x it.
  3. git commit now fails, as expected.
  4. gitui ignores the hook.

Expected behavior
pre-commit behaviour is the same when using git CLI.

Screenshots
N/A.

Context (please complete the following information):

  • OS/Distro + Version: Debian 12
  • GitUI Version: gitui 0.25.2
  • Rust version: rustc 1.76.0

Additional context
Relates to:

@savchenko savchenko added the bug Something isn't working label Jun 28, 2024
@extrawurst
Copy link
Collaborator

It seems your repro steps are not correct:
you say you create mkdir .githooks but then you create ./githooks/pre-commit (which is a subtle but very different folder name). if I fix this and create the pre-commit hook inside the path you configure: .githooks/pre-commit then gitui correct blocks the commit.

why in your case git rejects and gitui does not is beyond me

Screenshot 2024-06-28 at 09 12 51

@extrawurst extrawurst added the question Further information is requested label Jun 28, 2024
@savchenko
Copy link
Author

@extrawurst , a typo, fixed the original message. Git picks it up as it is configured to do so, in the local config:

[core]
    hooksPath = .githooks/

Turns out gitui correctly triggers the hook only when launched from the root folder (git rev-parse --show-toplevel).

Corresponding log record:

12:16:35 [TRACE] (1) git2_hooks::hookspath: [git2-hooks/src/hookspath.rs:114] run hook '".githooks/pre-commit"' in '"/home/user/foo/"'

And here is the successful attempt to commit the same file from one of the subfolders (e.g. /home/user/foo/src)

12:22:10 [ERROR] theme error ["/home/user/.config/gitui/theme.ron"]: 24:35: Failed to parse Colors: data did not match any variant of untagged enum ColorFormat
12:22:10 [TRACE] (1) gitui::app: [src/app.rs:154] open repo at: RefCell { value: Path(".") }
12:22:10 [TRACE] (6) mio::poll: [/home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/mio-0.8.11/src/poll.rs:551] registering event source with poller: token=Token(0), interests=READABLE
12:22:10 [TRACE] (6) mio::poll: [/home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/mio-0.8.11/src/poll.rs:551] registering event source with poller: token=Token(1), interests=READABLE
12:22:10 [TRACE] (1) asyncgit::status: [asyncgit/src/status.rs:102] request: [hash: 5275764462638972305] (type: WorkingDir)
12:22:10 [TRACE] (1) asyncgit::status: [asyncgit/src/status.rs:102] request: [hash: 4542120333235219920] (type: Stage)
12:22:10 [TRACE] (2) asyncgit::status: [asyncgit/src/status.rs:160] status fetched: 5275764462638972305 (type: WorkingDir)
12:22:10 [TRACE] (4) asyncgit::status: [asyncgit/src/status.rs:160] status fetched: 4542120333235219920 (type: Stage)
12:22:10 [TRACE] (1) gitui: [src/main.rs:215] app start: 21 ms
12:22:10 [TRACE] (1) gitui::app: [src/app.rs:375] update
12:22:10 [TRACE] (1) asyncgit::status: [asyncgit/src/status.rs:102] request: [hash: 7094696850961575051] (type: WorkingDir)
12:22:10 [TRACE] (1) asyncgit::status: [asyncgit/src/status.rs:102] request: [hash: 12783852074258472187] (type: Stage)
12:22:10 [TRACE] (2) asyncgit::status: [asyncgit/src/status.rs:160] status fetched: 7094696850961575051 (type: WorkingDir)
12:22:10 [TRACE] (4) asyncgit::status: [asyncgit/src/status.rs:160] status fetched: 12783852074258472187 (type: Stage)
12:22:10 [TRACE] (1) gitui::app: [src/app.rs:395] update_async: Git(Status)
12:22:10 [TRACE] (1) gitui::app: [src/app.rs:395] update_async: Git(Status)
12:22:10 [TRACE] (1) gitui::app: [src/app.rs:395] update_async: Git(Status)
12:22:10 [TRACE] (1) gitui::app: [src/app.rs:395] update_async: Git(Status)
12:22:11 [TRACE] (1) gitui::app: [src/app.rs:278] event: Input(Key(KeyEvent { code: Char('w'), modifiers: KeyModifiers(0x0), kind: Press, state: KeyEventState(0x0) }))
12:22:11 [TRACE] (1) asyncgit::diff: [asyncgit/src/diff.rs:101] request DiffParams { path: "foo.py", diff_type: Stage, options: DiffOptions { ignore_whitespace: false, context: 3, interhunk_lines: 0 } }
12:22:11 [TRACE] (1) gitui::app: [src/app.rs:395] update_async: Git(Diff)
12:22:11 [TRACE] (1) asyncgit::diff: [asyncgit/src/diff.rs:101] request DiffParams { path: "foo.py", diff_type: Stage, options: DiffOptions { ignore_whitespace: false, context: 3, interhunk_lines: 0 } }
12:22:11 [TRACE] (1) gitui::app: [src/app.rs:278] event: Input(Key(KeyEvent { code: Char('c'), modifiers: KeyModifiers(0x0), kind: Press, state: KeyEventState(0x0) }))
12:22:11 [TRACE] (1) gitui::app: [src/app.rs:278] event: Input(Key(KeyEvent { code: Char('R'), modifiers: KeyModifiers(SHIFT), kind: Press, state: KeyEventState(0x0) }))
12:22:12 [TRACE] (1) gitui::app: [src/app.rs:278] event: Input(Key(KeyEvent { code: Char('o'), modifiers: KeyModifiers(0x0), kind: Press, state: KeyEventState(0x0) }))
12:22:12 [TRACE] (1) gitui::app: [src/app.rs:278] event: Input(Key(KeyEvent { code: Char('g'), modifiers: KeyModifiers(0x0), kind: Press, state: KeyEventState(0x0) }))
12:22:12 [TRACE] (1) gitui::app: [src/app.rs:278] event: Input(Key(KeyEvent { code: Char('u'), modifiers: KeyModifiers(0x0), kind: Press, state: KeyEventState(0x0) }))
12:22:12 [TRACE] (1) gitui::app: [src/app.rs:278] event: Input(Key(KeyEvent { code: Char('e'), modifiers: KeyModifiers(0x0), kind: Press, state: KeyEventState(0x0) }))
12:22:12 [TRACE] (1) gitui::app: [src/app.rs:278] event: Input(Key(KeyEvent { code: Char('!'), modifiers: KeyModifiers(0x0), kind: Press, state: KeyEventState(0x0) }))
12:22:14 [TRACE] (1) gitui::app: [src/app.rs:278] event: Input(Key(KeyEvent { code: Char('d'), modifiers: KeyModifiers(CONTROL), kind: Press, state: KeyEventState(0x0) }))
12:22:14 [TRACE] (1) gitui::app: [src/app.rs:375] update
12:22:14 [TRACE] (1) asyncgit::diff: [asyncgit/src/diff.rs:101] request DiffParams { path: "foo.py", diff_type: Stage, options: DiffOptions { ignore_whitespace: false, context: 3, interhunk_lines: 0 } }
12:22:14 [TRACE] (1) asyncgit::status: [asyncgit/src/status.rs:102] request: [hash: 17309038260000894423] (type: WorkingDir)
12:22:14 [TRACE] (1) asyncgit::status: [asyncgit/src/status.rs:102] request: [hash: 9501808690652183810] (type: Stage)
12:22:14 [TRACE] (4) asyncgit::status: [asyncgit/src/status.rs:160] status fetched: 9501808690652183810 (type: Stage)
12:22:14 [TRACE] (5) asyncgit::status: [asyncgit/src/status.rs:160] status fetched: 17309038260000894423 (type: WorkingDir)
12:22:14 [TRACE] (1) gitui::app: [src/app.rs:395] update_async: Git(Diff)
12:22:14 [TRACE] (1) gitui::app: [src/app.rs:395] update_async: Git(Status)
12:22:14 [TRACE] (1) gitui::app: [src/app.rs:395] update_async: Git(Status)
12:22:14 [TRACE] (1) gitui::app: [src/app.rs:278] event: Input(Key(KeyEvent { code: Char('c'), modifiers: KeyModifiers(CONTROL), kind: Press, state: KeyEventState(0x0) }))

@savchenko savchenko changed the title Pre-commit hook is not executed Pre-commit hooks are executed only when launched from the git root Jul 25, 2024
@saiabishek1
Copy link

+1, the pre-commit hooks are run only when gitui is launched from the git root.

@extrawurst extrawurst added the good first issue Good for newcomers label Nov 10, 2024
@wessamfathi
Copy link
Contributor

I'd like to work on this if no one already is.

@wessamfathi
Copy link
Contributor

I cannot reproduce this issue on my end, as gitui runs the pre-commit correctly whether I'm running it from repo root or sub folders. I'm testing on the gitui repo, and from gitui/src and gitui/src/keys, and it works correctly in all cases.

Using the nightly 2025-01-14 build, macOS Sequoia, rustc 1.85.0.

Is this still an issue for you @savchenko @saiabishek1? Am I following the reproduction steps correctly?

@extrawurst
Copy link
Collaborator

@wessamfathi could you add a unit test for this in any case - we already have a few for hooks, should be easy to cover (in case we don’t have one maybe already for this subfolder thing)

@wessamfathi
Copy link
Contributor

wessamfathi commented Mar 16, 2025

I checked the hook test and it appears that there is one that does that job already test_hooks_commit_msg_reject_in_subfolder: it creates a folder foo and attempts to commit from within. I verified that it passes successfully on macOS.

Let me know if you mean something else and I'll do it. I'll try to test on Windows as well, but I cannot get OpenSSL to build no matter what I do.

@extrawurst
Copy link
Collaborator

Yeah I felt we had made a test for this already in the past. If you could get it tested on windows that would be awesome

@wessamfathi
Copy link
Contributor

The test passes on Windows 👍

@extrawurst extrawurst removed the good first issue Good for newcomers label Mar 17, 2025
@extrawurst
Copy link
Collaborator

@savchenko ok will close it as non-reproducible for now. feel free to reopen if this is still a problem on the most recent release

@extrawurst extrawurst removed the question Further information is requested label Mar 17, 2025
@savchenko
Copy link
Author

@extrawurst , I can reliably reproduce it with gitui v0.27 on Debian 13 (testing). What data would help you to pinpoint the issue?

@naseschwarz
Copy link
Contributor

naseschwarz commented Mar 18, 2025

Hi @savchenko: I've just tried to reproduce this using a fresh debian 13 container from docker.io, gitui 0.27 downloaded from the releases and the steps to reproduce from your initial issue. My commit is rejected as expected:

Image

Could you potentially create a syscall trace for us?

strace -fo gitui.strace.log gitui

... then try to commit in your test repo and upload gitui.strace.log.

In case you don't want to publish such a long log, I suggest you create a private repository, upload it there and invite me and anybody else who's interested.

@savchenko
Copy link
Author

@naseschwarz , reproduction steps:

  1. Create a repo
  2. Add to .githooks/pre-commit
#!/bin/env bash

set -euo pipefail

cd "$(git rev-parse --show-toplevel)" || exit 1

file_types=("txt")
flag="foo"
staged_files=$(git diff --cached --name-only --diff-filter=ACM)

is_excluded() {
    git check-ignore -q "$1"
    return $?
}

if [ -n "$staged_files" ]; then
    for type in "${file_types[@]}"; do
        files=$(echo "$staged_files" | grep "\.$type$" || echo "")
        if [ -z "$files" ]; then
            continue
        fi
        for file in $files; do
            if ! is_excluded "$file"; then
                if ! head -n 5 "$file" | grep -q "$flag"; then
                    echo "[ERROR] $file is missing the flag."
                    exit 1
                fi
            fi
        done
    done
fi
  1. git config --local core.hooksPath .githooks/
  2. echo bar > foo.txt && git add foo.txt
  3. git commit

The above will result in [ERROR] foo.txt is missing the flag. printed to the stdout.

  1. (important) mkdir -p some/long/path && cd some/long/path
  2. Open gitui, press w, then c, type arbitrary message, press Enter.

The commit will succeed. Please find the strace log attached.

gitui.strace.log.zip

@naseschwarz
Copy link
Contributor

Thanks, I can reproduce this now.

@naseschwarz naseschwarz reopened this Mar 18, 2025
@naseschwarz
Copy link
Contributor

naseschwarz commented Mar 18, 2025

@wessamfathi, do you still want to take care of this? I don't want to do a hostile takeover here. ;)

However, I've put together a failing test: d59f168.

The failure is due to a combination of two conditions, which was not obvious based on the original steps to reproduce, but is now:

  1. core.hooksPath is set to a relative path
  2. gitui is launched with a working directory that is not the working tree root.

@wessamfathi
Copy link
Contributor

@naseschwarz oh no worries! Feel free to take it. You're already on track, and now it feels a little bit over my head :)

I'll find something else for sure.

@extrawurst extrawurst added this to the v0.28 milestone Apr 4, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants