buf icon indicating copy to clipboard operation
buf copied to clipboard

Buf breaking: fatal: .git/index: index file open failed: Not a directory

Open jalaziz opened this issue 2 years ago • 4 comments

I'm trying to use the buf breaking hook with pre-commit and I am running into an odd problem that I have not been able to debug.

My pre-commit config looks like:

  - repo: https://github.com/bufbuild/buf
    rev: v1.26.1
    hooks:
      - id: buf-generate
        args: ['--template', 'api/proto/buf.gen.yaml', '--output', 'api/proto/']
        files: api/proto/
      - id: buf-breaking
        args: ['--against', '.git#branch=main,recurse_submodules=true']
      - id: buf-lint
      - id: buf-format
      - id: buf-mod-update
        args: ['api/proto']
        files: api/proto/
      - id: buf-mod-prune
        args: ['api/proto']
        files: api/proto/

When run with pre-commit run --all-files everything works fine.

However, when I attempt to commit changes that affect proto files, buf breaking fails with:

buf breaking.............................................................Failed
- hook id: buf-breaking
- exit code: 1

Failure: could not clone file:///Users/jalaziz/dev/foo/.git: exit status 128
Preparing worktree (detached HEAD 10f9f8b)
fatal: .git/index: index file open failed: Not a directory

jalaziz avatar Sep 25 '23 19:09 jalaziz

I have the same problem. @jalaziz Did you find a workaroud?

ddadonJoin avatar Oct 02 '23 15:10 ddadonJoin

I have the same problem. @jalaziz Did you find a workaroud?

@ddadonJoin Unfortunately not 😞. I had to disable it for now.

jalaziz avatar Oct 02 '23 16:10 jalaziz

i have the same issue, i think its because the repo is cloned with --bare. So there is no .git directory or index file. But not sure

berendjan avatar Feb 20 '24 18:02 berendjan

TL;DR run unset $(git rev-parse --local-env-vars) before calling buf in your pre-<whatever> hook.

I sort of figured why this happens. The culprit is env variable GIT_INDEX_FILE which is normally set to ".git/index" when hooks are running.

See in https://git-scm.com/docs/githooks :

Environment variables, such as GIT_DIR, GIT_WORK_TREE, etc., are exported so that Git commands run by the hook can correctly locate the repository. If your hook needs to invoke Git commands in a foreign repository or in a different working tree of the same repository, then it should clear these environment variables so they do not interfere with Git operations at the foreign location

This "If your hook needs to invoke Git commands in a foreign repository" applies to buf, as it creates temp bare repo and adds there a worktree, which is where it currently breaks for me due to GIT_INDEX_FILE pointing to that relative path ".git/index". Now I don't quite get which is current dir of executed command, but wherever it is, there is no ".git" folder there, so we see "Not a directory".

Following what doc says and running unset $(git rev-parse --local-env-vars) before running buf - solved that problem for me.

More precise unset GIT_INDEX_FILE also worked as well, which might indicate for buf maintainers that maybe cleaning that env var out, would be a good idea to support running "breaking" from git hook (along with adding some functional test for that maybe..).

strowk avatar Mar 08 '24 10:03 strowk

Thank you for providing the solution above, it addresses the concerns in the issue, so closing this for now!

doriable avatar Jun 10 '24 15:06 doriable

@doriable I don't think this is fixed yet. The actual issue is not addressed.

The issue here is with the pre-commit hooks published and maintained by Buf. It's not possible to add unset $(git rev-parse --local-env-vars) to the hooks by users of the published hooks.

Either this file needs to be updated to unset the variables or the buf breaking command needs to handle it.

jalaziz avatar Jun 15 '24 23:06 jalaziz

I concur, the approach I have posted is just a workaround, not "the issue is closed"-grade solution. It would make most sense if buf would support running from hooks without users having to do anything special.

F.e users do not have to know that buf creates bare repository in tmp and work with it got broken because environment variables are passed through. The most sensible thing here would be encapsulate buf operations with that bare git repo in a way that would make it work within hooks (i.e Unsetenv might do it).

@doriable , please consider reopening, thanks!

Interestingly enough, fix was already proposed, but rejected to be merged.. https://github.com/bufbuild/buf/pull/880/files#diff-8cef62359c658e0f295197edffbcb00770248e70319538a71a70168ac4337c41R315-R333

strowk avatar Jun 15 '24 23:06 strowk

A fix for this issue was included in #3095 will go out in the next release.

emcfarlane avatar Jul 23 '24 17:07 emcfarlane