lewis6991 / gitsigns.nvim

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

Chaining `gitsigns.diffthis()` after `gitsigns.show()` doesn't work #1091

Closed Iskustvo closed 1 month ago

Iskustvo commented 1 month ago

Description

At the time of writing, after gitsigns.show() is executed, 3 GitSignsUpdates are being triggered on the newly opened buffer. Note that some operations (like gitsigns.diffthis()) will not work properly unless all 3 events happened beforehand. Since gitsigns.show() accepts "then" callback for async continuation of work, I would expect the following code to work:

gitsigns.show("HEAD^", function() gitsigns.diffthis("HEAD^^") end)

Unfortunately, current implementation of gitsigns.show() seems to consistently execute "then" callback between first and second GitSignsUpdate event, thus gitsigns.diffthis() doesn't work at this stage.

Possible solution - Delay "then" callback of gitsigns.show() to be invoked after opened buffer is fully functional for further operations like gitsigns.diffthis().

Neovim version

NVIM v0.10.0

Operating system and version

Arch Linux (x86_64) Kernel: 6.9.9-arch1-1

Expected behavior

To see opened diff between HEAD^ and HEAD^^ snapshots of the file.

Actual behavior

gitsigns.diffthis() fails and I'm left with showed HEAD^ snapshot of the file.

Minimal config

for name, url in pairs{
  gitsigns = 'https://github.com/lewis6991/gitsigns.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
}

Steps to reproduce

  1. Create testing environment
    mkdir gitsigns_test
    cd gitsigns_test
    git init
    echo -e "aaa\nbbb\nccc" > file
    git add file
    git commit -m "add 3 lines"
    echo -e "aaaa\nbbbb\nccc" > file
    git commit -am "modify first two lines"
    echo -e "aaaa\nbbbbb\ncccc" > file
    git commit -am "modify last two lines"
  2. Open test file with minimal Neovim config
    nvim --clean -u minimal.lua file
  3. Navigate to third line (cccc).
  4. Execute chained gitsigns.show() and gitsigns.diffthis() functions.
    :lua require("gitsigns").show("HEAD^", function() require("gitsigns").diffthis("HEAD^^") end)
  5. Observe that gitsigns.show() successfully opened HEAD^ snapshot of a file, but there is no desired diff.
  6. Note that manually executing gitsigns.diffthis() now yields the expected result (after mentioned events passed):
    :lua require("gitsigns").diffthis("HEAD^^")

Gitsigns debug messages

0.45 D dprintf: Deriving GitSignsAdd from Added
0.51 D derive: Deriving GitSignsChange from Changed
0.59 D derive: Deriving GitSignsDelete from Removed
0.62 D derive: Deriving GitSignsChangedelete from GitSignsChange
0.64 D derive: Deriving GitSignsTopdelete from GitSignsDelete
0.69 D derive: Deriving GitSignsUntracked from GitSignsAdd
0.70 D derive: Deriving GitSignsAddNr from GitSignsAdd
0.72 D derive: Deriving GitSignsChangeNr from GitSignsChange
0.75 D derive: Deriving GitSignsDeleteNr from GitSignsDelete
0.76 D derive: Deriving GitSignsChangedeleteNr from GitSignsChangeNr
0.80 D derive: Deriving GitSignsTopdeleteNr from GitSignsDeleteNr
0.81 D derive: Deriving GitSignsUntrackedNr from GitSignsAddNr
0.83 D derive: Deriving GitSignsAddLn from DiffAdd
0.86 D derive: Deriving GitSignsChangeLn from DiffChange
0.91 D derive: Deriving GitSignsChangedeleteLn from GitSignsChangeLn
0.94 D derive: Deriving GitSignsUntrackedLn from GitSignsAddLn
0.95 D derive: Deriving GitSignsStagedAdd from GitSignsAdd
0.97 D derive: Deriving GitSignsStagedChange from GitSignsChange
1.00 D derive: Deriving GitSignsStagedDelete from GitSignsDelete
1.01 D derive: Deriving GitSignsStagedChangedelete from GitSignsChangedelete
1.03 D derive: Deriving GitSignsStagedTopdelete from GitSignsTopdelete
1.04 D derive: Deriving GitSignsStagedAddNr from GitSignsAddNr
1.05 D derive: Deriving GitSignsStagedChangeNr from GitSignsChangeNr
1.08 D derive: Deriving GitSignsStagedDeleteNr from GitSignsDeleteNr
1.11 D derive: Deriving GitSignsStagedChangedeleteNr from GitSignsChangedeleteNr
1.13 D derive: Deriving GitSignsStagedTopdeleteNr from GitSignsTopdeleteNr
1.17 D derive: Deriving GitSignsStagedAddLn from GitSignsAddLn
1.18 D derive: Deriving GitSignsStagedChangeLn from GitSignsChangeLn
1.19 D derive: Could not derive GitSignsStagedDeleteLn
1.21 D derive: Deriving GitSignsStagedChangedeleteLn from GitSignsChangedeleteLn
1.22 D derive: Could not derive GitSignsStagedTopdeleteLn
1.25 D derive: Deriving GitSignsAddPreview from DiffAdd
1.26 D derive: Deriving GitSignsDeletePreview from DiffDelete
1.28 D derive: Deriving GitSignsCurrentLineBlame from NonText
1.30 D derive: Deriving GitSignsAddInline from TermCursor
1.31 D derive: Deriving GitSignsDeleteInline from TermCursor
1.34 D derive: Deriving GitSignsChangeInline from TermCursor
1.36 D derive: Deriving GitSignsAddLnInline from GitSignsAddInline
1.37 D derive: Deriving GitSignsChangeLnInline from GitSignsChangeInline
1.38 D derive: Deriving GitSignsDeleteLnInline from GitSignsDeleteInline
1.40 D derive: Deriving GitSignsDeleteVirtLn from DiffDelete
1.41 D derive: Deriving GitSignsDeleteVirtLnInLine from GitSignsDeleteLnInline
1.42 D derive: Deriving GitSignsVirtLnum from GitSignsDeleteVirtLn
5.23 D attach(1): Attaching (trigger=BufReadPost)
5.30 D run_job: git --version
9.49 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
10.65 D run_job: git --no-pager --no-optional-locks --literal-pathspecs -c gc.auto=0 --git-dir /tmp/gitsigns_test/.git config user.name
11.68 D run_job: git --no-pager --no-optional-locks --literal-pathspecs -c gc.auto=0 --git-dir /tmp/gitsigns_test/.git -c core.quotepath=off ls-files --stage --others --exclude-standard --eol /tmp/gitsigns_test/file
13.02 D watch_gitdir(1): Watching git dir
13.09 D run_job: git --no-pager --no-optional-locks --literal-pathspecs -c gc.auto=0 --git-dir /tmp/gitsigns_test/.git show d70b101fd3f815557f68eff872bf0f8373f17314
15.10 D run_job: git --no-pager --no-optional-locks --literal-pathspecs -c gc.auto=0 --git-dir /tmp/gitsigns_test/.git show HEAD:file
16715.68 D show(3): Detached
16715.68 D show(3): Cache was nil
16715.73 D attach(3): Attaching (trigger=BufFilePost)
16715.76 D show(3): Gitsigns buffer for file '/tmp/gitsigns_test/file' from path 'gitsigns:///tmp/gitsigns_test/.git/HEAD^:file' on commit 'HEAD^'
16715.88 D run_job: git --no-pager --no-optional-locks --literal-pathspecs -c gc.auto=0 --git-dir /tmp/gitsigns_test/.git show HEAD^:file
16717.25 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
16718.17 D show(1): bufname gitsigns:///tmp/gitsigns_test/.git/HEAD^:file
16718.59 D run_job: git --no-pager --no-optional-locks --literal-pathspecs -c gc.auto=0 --git-dir /tmp/gitsigns_test/.git -c core.quotepath=off ls-tree HEAD^ /tmp/gitsigns_test/file
16719.90 D show(3): Watching git dir
16719.96 D run_job: git --no-pager --no-optional-locks --literal-pathspecs -c gc.auto=0 --git-dir /tmp/gitsigns_test/.git show 70db9132fdf518d67a66179a79647f6eaebbd9f3
16721.68 D run_job: git --no-pager --no-optional-locks --literal-pathspecs -c gc.auto=0 --git-dir /tmp/gitsigns_test/.git show HEAD^^:file
25290.61 D cli.run: Running action 'debug_messages' with arguments {}

Gitsigns cache

{ {
    bufnr = 1,
    compare_text = { "...",
      head = "aaaa",
      length = 4
    },
    compare_text_head = { "...",
      head = "aaaa",
      length = 4
    },
    file = "/tmp/gitsigns_test/file",
    force_next_update = false,
    git_obj = {
      encoding = "utf-8",
      file = "/tmp/gitsigns_test/file",
      i_crlf = false,
      mode_bits = "100644",
      object_name = "d70b101fd3f815557f68eff872bf0f8373f17314",
      relpath = "file",
      repo = <1>{
        abbrev_head = "master",
        detached = false,
        gitdir = "/tmp/gitsigns_test/.git",
        toplevel = "/tmp/gitsigns_test",
        username = "Iskustvo"
      },
      w_crlf = false
    },
    gitdir_watcher = <userdata 1>,
    hunks = { "...",
      length = 0
    },
    hunks_staged = { "...",
      length = 0
    },
    staged_diffs = { "...",
      length = 0
    }
  },
  [3] = {
    bufnr = 3,
    compare_text = { "...",
      head = "aaaa",
      length = 4
    },
    compare_text_head = { "...",
      head = "aaa",
      length = 4
    },
    file = "/tmp/gitsigns_test/file",
    force_next_update = false,
    git_obj = {
      encoding = "utf-8",
      file = "/tmp/gitsigns_test/file",
      mode_bits = "100644",
      object_name = "70db9132fdf518d67a66179a79647f6eaebbd9f3",
      relpath = "file",
      repo = <table 1>,
      revision = "HEAD^"
    },
    gitdir_watcher = <userdata 2>,
    hunks = { "...",
      length = 0
    },
    hunks_staged = { "...",
      head = {
        added = {
          count = 2,
          lines = { "aaaa", "bbbb" },
          start = 1
        },
        head = "@@ -1,2 +1,2 @@",
        removed = {
          count = 2,
          lines = { "aaa", "bbb" },
          start = 1
        },
        type = "change",
        vend = 2
      },
      length = 1
    },
    staged_diffs = { "...",
      length = 0
    }
  }
}