greenbone / autohooks

Library for managing git hooks
https://greenbone.github.io/autohooks/
GNU General Public License v3.0
189 stars 22 forks source link

autohooks.utils.GitError: Git command '['git', '-C', '...', 'rev-parse', '--git-dir']' returned non-zero exit status 128 #147

Closed VictorAtPL closed 3 years ago

VictorAtPL commented 3 years ago

Hi,

I have autohooks installed using pythonpath method.

If I run git commit --amend -m "Test" in root directory of repository, the autohooks runs correctly:

➜  test git:(temp) ✗ gc --amend -m "Test"
ℹ autohooks => pre-commit
ℹ     Running check_top_directory_names
✖         Could not validate top directory name of path testes/dsdsa

However if I run it inside the testes directory, I get following error:

➜  testes git:(temp) ✗ gc --amend -m "Test"
fatal: not a git repository: '.git'
could not determine .git directory. 
Traceback (most recent call last):
  File ".git/hooks/pre-commit", line 8, in <module>
    sys.exit(run())
  File "/home/ubuntu/anaconda3/lib/python3.7/site-packages/autohooks/precommit/run.py", line 90, in run
    pre_commit_hook = PreCommitHook()
  File "/home/ubuntu/anaconda3/lib/python3.7/site-packages/autohooks/hooks.py", line 44, in __init__
    self.pre_commit_hook_path = get_pre_commit_hook_path()
  File "/home/ubuntu/anaconda3/lib/python3.7/site-packages/autohooks/hooks.py", line 35, in get_pre_commit_hook_path
    git_hook_dir_path = get_git_hook_directory_path()
  File "/home/ubuntu/anaconda3/lib/python3.7/site-packages/autohooks/utils.py", line 70, in get_git_hook_directory_path
    git_dir_path = get_git_directory_path()
  File "/home/ubuntu/anaconda3/lib/python3.7/site-packages/autohooks/utils.py", line 54, in get_git_directory_path
    raise e from None
  File "/home/ubuntu/anaconda3/lib/python3.7/site-packages/autohooks/utils.py", line 49, in get_git_directory_path
    git_dir = exec_git('-C', pwd, 'rev-parse', '--git-dir').rstrip()
  File "/home/ubuntu/anaconda3/lib/python3.7/site-packages/autohooks/utils.py", line 42, in exec_git
    raise GitError(e.returncode, e.cmd, e.output, e.stderr) from None
autohooks.utils.GitError: Git command '['git', '-C', '...', 'rev-parse', '--git-dir']' returned non-zero exit status 128

If I run git -C `pwd` rev-parse --git-dir command inside the tested directory, I get proper result - a path which points to .git directory in repository root path.

Why command executed using exec_git method returns non-zero exit status 128 and the same command executed directly from the terminal returns proper result?

Btw. In my case .autohooks directory is another git submodule, because I want to store code of hooks in other repository than the one where pre-commit hooks are used.

bjoernricks commented 3 years ago

'['git', '-C', '...', 'rev-parse', '--git-dir']' is of course wrong. There is no directory path with three dots. Maybe finding the the right git root directory is broken in this case.

@VictorAtPL could you give use the concrete directory layout?

VictorAtPL commented 3 years ago

Hi @bjoernricks , I replaced real path by ... :-).

The real path is /home/piotr.CENSORED/repos/CENSORED/test/testes and .git dir is located in /home/piotr.CENSORED/repos/CENSORED/test/.

VictorAtPL commented 3 years ago

Additionally, it's really weird that if I manually run python interpreter and invoke the get_git_directory_path() method, then I do not get such exception as when I execute git commit.

➜  testes git:(temp) ✗ pwd
/home/piotr.CENSORED/repos/CENSORED/test/testes
➜  testes git:(temp) ✗ ipython
Python 3.7.10 (default, Feb 26 2021, 18:47:35) 
Type 'copyright', 'credits' or 'license' for more information
IPython 7.22.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: from autohooks import utils

In [2]: utils.get_git_directory_path
Out[2]: <function autohooks.utils.get_git_directory_path() -> pathlib.Path>

In [3]: utils.get_git_directory_path()
Out[3]: PosixPath('/home/piotr.CENSORED/repos/CENSORED/test/.git')
bjoernricks commented 3 years ago

Did you run git commit also in that /home/piotr.CENSORED/repos/CENSORED/test/testes directory?

VictorAtPL commented 3 years ago

Yes. git commit in root directory (test) works, in (test/testes) directory doesn't work and returns:

fatal: not a git repository: '.git'
could not determine .git directory. 
Traceback (most recent call last):
  File ".git/hooks/pre-commit", line 8, in <module>
    sys.exit(run())
  File "/home/ubuntu/anaconda3/lib/python3.7/site-packages/autohooks/precommit/run.py", line 90, in run
    pre_commit_hook = PreCommitHook()
  File "/home/ubuntu/anaconda3/lib/python3.7/site-packages/autohooks/hooks.py", line 44, in __init__
    self.pre_commit_hook_path = get_pre_commit_hook_path()
  File "/home/ubuntu/anaconda3/lib/python3.7/site-packages/autohooks/hooks.py", line 35, in get_pre_commit_hook_path
    git_hook_dir_path = get_git_hook_directory_path()
  File "/home/ubuntu/anaconda3/lib/python3.7/site-packages/autohooks/utils.py", line 70, in get_git_hook_directory_path
    git_dir_path = get_git_directory_path()
  File "/home/ubuntu/anaconda3/lib/python3.7/site-packages/autohooks/utils.py", line 54, in get_git_directory_path
    raise e from None
  File "/home/ubuntu/anaconda3/lib/python3.7/site-packages/autohooks/utils.py", line 49, in get_git_directory_path
    git_dir = exec_git('-C', pwd, 'rev-parse', '--git-dir').rstrip()
  File "/home/ubuntu/anaconda3/lib/python3.7/site-packages/autohooks/utils.py", line 42, in exec_git
    raise GitError(e.returncode, e.cmd, e.output, e.stderr) from None
autohooks.utils.GitError: Git command '['git', '-C', '/home/piotr.CENSORED/repos/CENSORED/test/testes', 'rev-parse', '--git-dir']' returned non-zero exit status 128
VictorAtPL commented 3 years ago

And if in test/testes I invoke git commit with --no-verify - it also works. So indeed there is some problem while executing the pre-commit hook. Somehow if python is invoked from pre-commit hook then the interpreter is in another directory and doesn't find .git directory?

VictorAtPL commented 3 years ago

Also, suprisingly, if I run this command which returns exit status 128 anywhere else in console, e.g. in home directory which is not .git repository, it also works properly:

piotr.CENSORED@CENSORED:~/repos$ git -C /home/piotr.CENSORED/repos/CENSORED/test/testes rev-parse --git-dir
/home/piotr.CENSORED/repos/CENSORED/test/.git

So this information fatal: not a git repository: '.git' is really weird, because this command git -C ... rev-... --git-... doesn't need to be invoked inside git repo.

VictorAtPL commented 3 years ago

Here is a way how to reproduce bug:

➜  repos mkdir test-autohooks
➜  repos cd test-autohooks 
➜  test-autohooks git init
Initialized empty Git repository in /home/piotr.CENSORED/repos/test-autohooks/.git/
➜  test-autohooks git:(master) mkdir .autohooks
➜  test-autohooks git:(master) autohooks activate
⚠ autohooks is not enabled in your /home/piotr.CENSORED/repos/test-autohooks/pyproject.toml file. Run 'autohooks check' for more details.
✓ autohooks pre-commit hook installed at /home/piotr.CENSORED/repos/test-autohooks/.git/hooks/pre-commit using pythonpath mode.
➜  test-autohooks git:(master) ls -l
total 0
➜  test-autohooks git:(master) touch test
➜  test-autohooks git:(master) ✗ ga .
➜  test-autohooks git:(master) ✗ gcmsg "test"
ℹ autohooks => pre-commit
[master (root-commit) 73a7bc5] test
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 test
➜  test-autohooks git:(master) mkdir test2
➜  test-autohooks git:(master) cd test2 
➜  test2 git:(master) touch test2
➜  test2 git:(master) ✗ gcmsg "test2"
fatal: not a git repository: '.git'
could not determine .git directory. 
Traceback (most recent call last):
  File ".git/hooks/pre-commit", line 8, in <module>
    sys.exit(run())
  File "/home/ubuntu/anaconda3/lib/python3.7/site-packages/autohooks/precommit/run.py", line 90, in run
    pre_commit_hook = PreCommitHook()
  File "/home/ubuntu/anaconda3/lib/python3.7/site-packages/autohooks/hooks.py", line 44, in __init__
    self.pre_commit_hook_path = get_pre_commit_hook_path()
  File "/home/ubuntu/anaconda3/lib/python3.7/site-packages/autohooks/hooks.py", line 35, in get_pre_commit_hook_path
    git_hook_dir_path = get_git_hook_directory_path()
  File "/home/ubuntu/anaconda3/lib/python3.7/site-packages/autohooks/utils.py", line 70, in get_git_hook_directory_path
    git_dir_path = get_git_directory_path()
  File "/home/ubuntu/anaconda3/lib/python3.7/site-packages/autohooks/utils.py", line 54, in get_git_directory_path
    raise e from None
  File "/home/ubuntu/anaconda3/lib/python3.7/site-packages/autohooks/utils.py", line 49, in get_git_directory_path
    git_dir = exec_git('-C', pwd, 'rev-parse', '--git-dir').rstrip()
  File "/home/ubuntu/anaconda3/lib/python3.7/site-packages/autohooks/utils.py", line 42, in exec_git
    raise GitError(e.returncode, e.cmd, e.output, e.stderr) from None
autohooks.utils.GitError: Git command '['git', '-C', '/home/piotr.CENSORED/repos/test-autohooks/test2', 'rev-parse', '--git-dir']' returned non-zero exit status 128

When I do it on my Ubuntu installation - the problem occures, however if I do it on my MacOSX - I do not have such error. Really, really weird. Looks like there is some misconfiguration at my side, not bug in the code.

y0urself commented 3 years ago

On my MacBook:

> $:$ mkdir xyz
> $:$ cd xyz
> $:/xyz$ git init
Initialized empty Git repository in /Users/y0urself/Documents/greenbone/xyz/.git/
> $:/xyz$ autohooks activate
> $:/xyz$ touch testenbone/xyz/.git/hooks/pre-commit using pythonpath mode.  details.                                                                                                                                                                                                             [ wa [ ok ]
> $:/xyz$ git add test
> $:/xyz$ git commit -m "Test"
[master (root-commit) 35aa571] Test
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 test
> $:/xyz$ mkdir test2
> $:/xyz$ cd test2
> $:/xyz/test2$ touch test2
> $:/xyz/test2$ git add test2
> $:/xyz/test2$ git commit -m "Test2"
[master 8b52385] Test2t
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 test2/test2
$ git --version
git version 2.20.1 (Apple Git-117)
$ python --version
Python 3.8.1

Funny thing: The message on autohooks activate is broken (for me) ... there is no newline and the bash directory thingy is printed over the message from autohooks ...

y0urself commented 3 years ago

On debian buster:

x@y:~/source$ mkdir xyz
x@y:~/source$ cd xyz
x@y:~/source/xyz$ git init
Initialized empty Git repository in /home/jloechte/source/xyz/.git/
x@y:~/source/xyz$ autohooks activate
⚠ autohooks is not enabled in your /home/jloechte/source/xyz/pyproject.toml file. Run 'autohooks check' for more details.
✓ autohooks pre-commit hook installed at /home/jloechte/source/xyz/.git/hooks/pre-commit using pythonpath mode.
x@y:~/source/xyz$ touch test
x@y:~/source/xyz$ git add test 
x@y:~/source/xyz$ git commit -m "Test"
ℹ autohooks => pre-commit
[master (root-commit) 0d9b8db] Test
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 test
x@y:~/source/xyz$ mkdir test2
x@y:~/source/xyz$ cd test2
x@y:~/source/xyz/test2$ touch test2
x@y:~/source/xyz/test2$ git add test2 
x@y:~/source/xyz/test2$ git commit -m "Test2"
ℹ autohooks => pre-commit
[master cdc794c] Test2
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 test2/test2
x@y:~/source/xyz/test2$ 

So I do not have any problems here ...

x@y:~/source/xyz/test2$ git --version
git version 2.20.1
x@y:~/source/xyz/test2$ python --version
Python 3.7.3
bjoernricks commented 3 years ago

Maybe a bug in the git version?

bjoernricks commented 3 years ago

Just tested it on my machine too and it works as expected.

> cat /etc/lsb-release 
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=21.04
DISTRIB_CODENAME=hirsute
DISTRIB_DESCRIPTION="Ubuntu 21.04"
> python3 --version
Python 3.9.5
> git --version    
git version 2.30.2
y0urself commented 3 years ago

I guess not ... I have older versions than you .... and I also do not think it is a problem with python 3.7?

VictorAtPL commented 3 years ago

That's really weird. I confirm it's hard to replicate this issue somewhere else than in my Ubuntu setup.

I started digging and I replace whole content of ./git/hooks/pre-commit with:

git -C `pwd` rev-parse --git-dir
exit 1

If I execute git commit in testes, it surprisingly returns just .git, but that's not truth (I am in sub-dir, not root dir):

➜  testes git:(temp) pwd                          
/home/piotr.CENSORED/repos/CENSORED/test/testes
➜  testes git:(temp) gcmsg "fdsfds" --amend       
.git

If I use not --git-dir, but --absolute-git-dir, it returns proper path:

➜  testes git:(temp) pwd                          
/home/piotr.CENSORED/repos/CENSORED/test/testes
➜  testes git:(temp) gcmsg "fdsfds" --amend
/home/piotr.CENSORED/repos/CENSORED/test/.git

However if in `.git/hooks/pre-commit' I put:

#!/usr/bin/env python
import subprocess as sb
import sys
import os

proc = sb.Popen(['git', '-C', os.environ['PWD'], 'rev-parse', '--absolute-git-dir'], stdout=sb.PIPE)
stdout, stderr = proc.communicate()

print(stdout)
print(stderr)
sys.exit(1)

then it returns:

fatal: not a git repository: '.git'
b''
None

but only if I execute it in testes/. If I execute it in GIT repo root directory, it returns:

b'/home/piotr.CENSORED/repos/CENSORED/test/.git\n'
None

Any ideas why same code executed in root dir and sub dir gives different results? Any ideas how to debug it? :|

VictorAtPL commented 3 years ago

I decided to switch to pre-commit and problem doesn't occure there.