lewis6991 / gitsigns.nvim

Git integration for buffers
MIT License
4.93k stars 186 forks source link

Conflict with which-key, `outside repository'-error #1117

Open kimabrandt opened 1 week ago

kimabrandt commented 1 week ago

Description

With installed which-key-plugin and gitsigns debug_mode enabled, gitsigns - most of the time, but not always - gives the following error, when using git difftool (with debug_mode disabled, this only happens sometimes, without the error and stack traceback):

Error executing luv callback:
...ns_issue/gitsigns_issue/gitsigns//lua/gitsigns/async.lua:95: The async coroutine failed: ...igns_issue/gitsigns_issue/gitsigns//lua/gitsigns/git.lua:151: fatal: /tmp/gitsi
gns_issue/file: '/tmp/gitsigns_issue/file' is outside repository at '/tmp/git-blob-Wbd6Ch'

stack traceback:
        [C]: in function 'error'
        ...ssue/gitsigns_issue/gitsigns//lua/gitsigns/debug/log.lua:123: in function 'eprint'
        ...ssue/gitsigns_issue/gitsigns//lua/gitsigns/debug/log.lua:128: in function 'eprint'
        ...igns_issue/gitsigns_issue/gitsigns//lua/gitsigns/git.lua:151: in function 'file_info'
        ...igns_issue/gitsigns_issue/gitsigns//lua/gitsigns/git.lua:80: in function 'update'
        ...igns_issue/gitsigns_issue/gitsigns//lua/gitsigns/git.lua:422: in function 'new'
        ...s_issue/gitsigns_issue/gitsigns//lua/gitsigns/attach.lua:280: in function 'fn'
        ...issue/gitsigns_issue/gitsigns//lua/gitsigns/debounce.lua:68: in function 'attach_throttled'
        ...s_issue/gitsigns_issue/gitsigns//lua/gitsigns/attach.lua:431: in function <...s_issue/gitsigns_issue/gitsigns//lua/gitsigns/attach.lua:430>
stack traceback:
        [C]: in function 'error'
        ...ns_issue/gitsigns_issue/gitsigns//lua/gitsigns/async.lua:95: in function 'cb'
        ...ns_issue/gitsigns_issue/gitsigns//lua/gitsigns/async.lua:145: in function 'on_exit'
        /usr/share/nvim/runtime/lua/vim/_system.lua:300: in function </usr/share/nvim/runtime/lua/vim/_system.lua:270>

Neovim version

NVIM v0.10.1 Build type: Release LuaJIT 2.1.1720049189

Operating system and version

NAME="Arch Linux" BUILD_ID=rolling

Expected behavior

No error should be shown, even though it's non-critical.

Actual behavior

It seems, as if gitsigns did not attach to the file on the right; the file inside the repository!? This also happens with disabled debug_mode.

On the other hand, gitsigns seems to always attach - also with disabled debug_mode - to the file on the left; the /tmp/git-blob-<random>/<filename>. I'm not sure if this is the expected behavior or not?! Since I could imagine, that it should be ignored by gitsigns!? This may be unrelated to this issue!?

Minimal config

for name, url in pairs({
  gitsigns = "https://github.com/lewis6991/gitsigns.nvim",
  which_key = "https://github.com/folke/which-key.nvim",
}) do
  local install_path = vim.fn.fnamemodify("gitsigns_issue/" .. name, ":p")
  if vim.fn.isdirectory(install_path) == 0 then
    vim.fn.system({ "git", "clone", "--depth=1", url, install_path })
  end
  vim.opt.runtimepath:append(install_path)
end

require("gitsigns").setup({
  debug_mode = true,
})

require("which-key").setup()

Steps to reproduce

  1. mkdir gitsigns_issue
  2. cd gitsigns_issue
  3. git init
  4. touch file
  5. git add file
  6. git commit -m 'initial commit'
  7. nvim minimal.lua
  8. git config difftool.gsvimdiff.cmd 'nvim --clean -u minimal.lua -d "$LOCAL" "$REMOTE"'
  9. git config difftool.prompt false
  10. echo 123 > file
  11. nvim --clean -u minimal.lua -cq
  12. git difftool --tool=gsvimdiff

Gitsigns debug messages

0.52 D dprintf: Deriving GitSignsAdd from Added
0.54 D derive: Deriving GitSignsChange from Changed
0.59 D derive: Deriving GitSignsDelete from Removed
0.61 D derive: Deriving GitSignsChangedelete from GitSignsChange
0.64 D derive: Deriving GitSignsTopdelete from GitSignsDelete
0.65 D derive: Deriving GitSignsUntracked from GitSignsAdd
0.67 D derive: Deriving GitSignsAddNr from GitSignsAdd
0.69 D derive: Deriving GitSignsChangeNr from GitSignsChange
0.72 D derive: Deriving GitSignsDeleteNr from GitSignsDelete
0.73 D derive: Deriving GitSignsChangedeleteNr from GitSignsChangeNr
0.75 D derive: Deriving GitSignsTopdeleteNr from GitSignsDeleteNr
0.77 D derive: Deriving GitSignsUntrackedNr from GitSignsAddNr
0.79 D derive: Deriving GitSignsAddLn from DiffAdd
0.81 D derive: Deriving GitSignsChangeLn from DiffChange
0.86 D derive: Deriving GitSignsChangedeleteLn from GitSignsChangeLn
0.87 D derive: Deriving GitSignsUntrackedLn from GitSignsAddLn
0.88 D derive: Deriving GitSignsAddCul from GitSignsAdd
0.89 D derive: Deriving GitSignsChangeCul from GitSignsChange
0.91 D derive: Deriving GitSignsDeleteCul from GitSignsDelete
0.92 D derive: Deriving GitSignsChangedeleteCul from GitSignsChangeCul
0.93 D derive: Deriving GitSignsTopdeleteCul from GitSignsDeleteCul
0.94 D derive: Deriving GitSignsUntrackedCul from GitSignsAddCul
0.95 D derive: Deriving GitSignsStagedAdd from GitSignsAdd
0.97 D derive: Deriving GitSignsStagedChange from GitSignsChange
1.01 D derive: Deriving GitSignsStagedDelete from GitSignsDelete
1.02 D derive: Deriving GitSignsStagedChangedelete from GitSignsChangedelete
1.04 D derive: Deriving GitSignsStagedTopdelete from GitSignsTopdelete
1.06 D derive: Deriving GitSignsStagedAddNr from GitSignsAddNr
1.07 D derive: Deriving GitSignsStagedChangeNr from GitSignsChangeNr
1.09 D derive: Deriving GitSignsStagedDeleteNr from GitSignsDeleteNr
1.10 D derive: Deriving GitSignsStagedChangedeleteNr from GitSignsChangedeleteNr
1.11 D derive: Deriving GitSignsStagedTopdeleteNr from GitSignsTopdeleteNr
1.12 D derive: Deriving GitSignsStagedAddLn from GitSignsAddLn
1.15 D derive: Deriving GitSignsStagedChangeLn from GitSignsChangeLn
1.16 D derive: Could not derive GitSignsStagedDeleteLn
1.18 D derive: Deriving GitSignsStagedChangedeleteLn from GitSignsChangedeleteLn
1.20 D derive: Could not derive GitSignsStagedTopdeleteLn
1.22 D derive: Deriving GitSignsStagedAddCul from GitSignsAddCul
1.23 D derive: Deriving GitSignsStagedChangeCul from GitSignsChangeCul
1.25 D derive: Deriving GitSignsStagedDeleteCul from GitSignsDeleteCul
1.26 D derive: Deriving GitSignsStagedChangedeleteCul from GitSignsChangedeleteCul
1.31 D derive: Deriving GitSignsStagedTopdeleteCul from GitSignsTopdeleteCul
1.33 D derive: Deriving GitSignsAddPreview from DiffAdd
1.35 D derive: Deriving GitSignsDeletePreview from DiffDelete
1.37 D derive: Deriving GitSignsCurrentLineBlame from NonText
1.38 D derive: Deriving GitSignsAddInline from TermCursor
1.39 D derive: Deriving GitSignsDeleteInline from TermCursor
1.41 D derive: Deriving GitSignsChangeInline from TermCursor
1.42 D derive: Deriving GitSignsAddLnInline from GitSignsAddInline
1.43 D derive: Deriving GitSignsChangeLnInline from GitSignsChangeInline
1.45 D derive: Deriving GitSignsDeleteLnInline from GitSignsDeleteInline
1.48 D derive: Deriving GitSignsDeleteVirtLn from DiffDelete
1.49 D derive: Deriving GitSignsDeleteVirtLnInLine from GitSignsDeleteLnInline
1.51 D derive: Deriving GitSignsVirtLnum from GitSignsDeleteVirtLn
5.50 D attach(1): Attaching (trigger=BufReadPost)
5.55 D run_job: git --version
9.30 D attach(2): Attaching (trigger=BufReadPost)
9.38 D run_job: git --version
15.41 D run_job: git --no-pager --no-optional-locks --literal-pathspecs -c gc.auto=0 rev-parse --show-toplevel --absolute-git-dir --abbrev-ref HEAD
16.03 D run_job: git --no-pager --no-optional-locks --literal-pathspecs -c gc.auto=0 rev-parse --show-toplevel --absolute-git-dir --abbrev-ref HEAD
16.79 D run_job: git --no-pager --no-optional-locks --literal-pathspecs -c gc.auto=0 --git-dir /tmp/gitsigns_issue/.git --work-tree /tmp/git-blob-Wbd6Ch config user.name
19.49 D run_job: git --no-pager --no-optional-locks --literal-pathspecs -c gc.auto=0 --git-dir /tmp/gitsigns_issue/.git --work-tree /tmp/git-blob-Wbd6Ch -c core.quotepath=off ls-files --stage --others --exclude-standard --eol /tmp/git-blob-Wbd6Ch/file
19.99 D run_job: git --no-pager --no-optional-locks --literal-pathspecs -c gc.auto=0 --git-dir /tmp/gitsigns_issue/.git --work-tree /tmp/git-blob-Wbd6Ch -c core.quotepath=off ls-files --stage --others --exclude-standard --eol /tmp/gitsigns_issue/file
20.89 D watch_gitdir(1): Watching git dir
20.93 D run_job: git --no-pager --no-optional-locks --literal-pathspecs -c gc.auto=0 --git-dir /tmp/gitsigns_issue/.git --work-tree /tmp/git-blob-Wbd6Ch show e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
21.34 E ...igns_issue/gitsigns_issue/gitsigns//lua/gitsigns/git.lua<151>: fatal: /tmp/gitsigns_issue/file: '/tmp/gitsigns_issue/file' is outside repository at '/tmp/git-blob-Wbd6Ch'

stack traceback:
        ...ssue/gitsigns_issue/gitsigns//lua/gitsigns/debug/log.lua:121: in function 'eprint'
        ...ssue/gitsigns_issue/gitsigns//lua/gitsigns/debug/log.lua:128: in function 'eprint'
        ...igns_issue/gitsigns_issue/gitsigns//lua/gitsigns/git.lua:151: in function 'file_info'
        ...igns_issue/gitsigns_issue/gitsigns//lua/gitsigns/git.lua:80: in function 'update'
        ...igns_issue/gitsigns_issue/gitsigns//lua/gitsigns/git.lua:422: in function 'new'
        ...s_issue/gitsigns_issue/gitsigns//lua/gitsigns/attach.lua:280: in function 'fn'
        ...issue/gitsigns_issue/gitsigns//lua/gitsigns/debounce.lua:68: in function 'attach_throttled'
        ...s_issue/gitsigns_issue/gitsigns//lua/gitsigns/attach.lua:431: in function <...s_issue/gitsigns_issue/gitsigns//lua/gitsigns/attach.lua:430>
48265.63 D run_job: git --no-pager --no-optional-locks --literal-pathspecs -c gc.auto=0 rev-parse --show-toplevel --absolute-git-dir --abbrev-ref HEAD
48268.19 D run_job: git --no-pager --no-optional-locks --literal-pathspecs -c gc.auto=0 --git-dir /tmp/gitsigns_issue/.git --work-tree /tmp/git-blob-Wbd6Ch show HEAD:file
49759.89 D cli.run: Running action 'debug_messages' with arguments {}
57316.32 D cli.run: Running action 'debug_messages' with arguments {}

Gitsigns cache

{ {
    bufnr = 1,
    compare_text = { "...",
      head = "",
      length = 1
    },
    compare_text_head = { "...",
      head = "",
      length = 1
    },
    file = "/tmp/git-blob-Wbd6Ch/file",
    force_next_update = false,
    git_obj = {
      encoding = "utf-8",
      file = "/tmp/git-blob-Wbd6Ch/file",
      i_crlf = false,
      mode_bits = "100644",
      object_name = "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391",
      relpath = "file",
      repo = {
        abbrev_head = "main",
        detached = true,
        gitdir = "/tmp/gitsigns_issue/.git",
        toplevel = "/tmp/git-blob-Wbd6Ch",
        username = "Kim A. Brandt"
      },
      w_crlf = false
    },
    gitdir_watcher = <userdata 1>,
    hunks = { "...",
      head = {
        added = {
          count = 1,
          lines = { "" },
          start = 1
        },
        head = "@@ -0 +1,1 @@",
        removed = {
          count = 0,
          lines = {},
          start = 0
        },
        type = "add",
        vend = 1
      },
      length = 1
    },
    hunks_staged = { "...",
      length = 0
    },
    staged_diffs = { "...",
      length = 0
    }
  } }
kimabrandt commented 1 week ago

More precisely: The error is (sometimes) happening with both enabled and disabled debug_mode. Only with debug_mode enabled, the Error executing luv callback and stack traceback are shown. In both cases, the right hand side diff-file, is (sometimes) not attached to. I guess, this is when the error happens!?

kimabrandt commented 1 week ago

Here's a fix, how I would imagine it to work. It fixes both the error and my suggested change; ignore files inside the /tmp/git-blob-*-directory:

diff --git a/lua/gitsigns/git.lua b/lua/gitsigns/git.lua
index bec3d35..f81cf2c 100644
--- a/lua/gitsigns/git.lua
+++ b/lua/gitsigns/git.lua
@@ -399,6 +399,10 @@ function Obj.new(file, revision, encoding, gitdir, toplevel)
     log.dprint('In git dir')
     return nil
   end
+  if vim.fn.fnamemodify(file, ":h"):match("^/tmp/git[-]blob[-]") then
+    log.dprint('Outside repository')
+    return nil
+  end

   if not vim.startswith(file, '/') and toplevel then
     file = toplevel .. util.path_sep .. file
kimabrandt commented 1 week ago

I havn't yet figured out - why/how at 19.99 in the Gitsigns debug messages - the command is pairing a work-tree (toplevel) and a file, that cause the fatal: /tmp/gitsigns_issue/file: '/tmp/gitsigns_issue/file' is outside repository at '/tmp/git-blob-Wbd6Ch'-error!?