nvim-telescope / telescope.nvim

Find, Filter, Preview, Pick. All lua, all the time.
MIT License
14.75k stars 808 forks source link

Encountered an error when using `git_command` in `git_bcommits` #2517

Open keaising opened 1 year ago

keaising commented 1 year ago

Description

In my use case, I use customized git_command in git_bcommits, and meet error

Error executing luv callback:
...repro/plugins/plenary.nvim/lua/plenary/async/control.lua:122: Oneshot channel can only send once
stack traceback:
        [C]: in function 'assert'
        ...repro/plugins/plenary.nvim/lua/plenary/async/control.lua:122: in function 'eof_tx'
        ...otfile/.repro/plugins/telescope.nvim/lua/telescope/_.lua:142: in function <...otfile/.repro/plugins/telescope.nvim/lua/telescope/_.lua:136>

But if I use default command, it's ok

My customized command:

git log --date="format:%y/%m/%d" --pretty="format:%C(auto) %h %ad %s"

Default command in Telescope

git log --pretty=oneline --abbrev-commit

I think maybe my customized command missed something needed, but I can not find the difference between the results of these two command

PS. This issue can be reliably reproduced only on some files. If you cannot reproduce it in your projects or files, please try this file https://github.com/keaising/dotfile/blob/master/nvim/.config/nvim/lua/plugins/telescope.lua , the issue can be reliably reproduced on it.

Neovim version

NVIM v0.9.0
Build type: Release
LuaJIT 2.1.0-beta3

   system vimrc file: "$VIM/sysinit.vim"
  fall-back for $VIM: "/share/nvim"

Run :checkhealth for more info

Operating system and version

ArchLinux, latest

Telescope version / branch / rev

master branch

checkhealth telescope

telescope: require("telescope.health").check()

Checking for required plugins ~
- OK plenary installed.
- OK nvim-treesitter installed.

Checking external dependencies ~
- OK rg: found ripgrep 13.0.0
- OK fd: found fd 8.7.0

===== Installed extensions ===== ~

Steps to reproduce

  1. git clone git@github.com:keaising/dotfile.git
  2. copy and paste minimal.lua content into minimal.lua in dotfile folder
  3. nvim -u minimal.lua nvim/.config/nvim/lua/plugins/telescope.lua
  4. Wait lazy install all plugins needed
  5. press gb can meet the error
  6. press gj will not meet the error

Expected behavior

No error

Actual behavior

Error executing luv callback:
...repro/plugins/plenary.nvim/lua/plenary/async/control.lua:122: Oneshot channel can only send once
stack traceback:
        [C]: in function 'assert'
        ...repro/plugins/plenary.nvim/lua/plenary/async/control.lua:122: in function 'eof_tx'
        ...otfile/.repro/plugins/telescope.nvim/lua/telescope/_.lua:142: in function <...otfile/.repro/plugins/telescope.nvim/lua/telescope/_.lua:136>

Minimal config

-- DO NOT change the paths and don't remove the colorscheme
local root = vim.fn.fnamemodify("./.repro", ":p")

-- set stdpaths to use .repro
for _, name in ipairs({ "config", "data", "state", "cache" }) do
    vim.env[("XDG_%s_HOME"):format(name:upper())] = root .. "/" .. name
end

-- bootstrap lazy
local lazypath = root .. "/plugins/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
    vim.fn.system({
        "git",
        "clone",
        "--filter=blob:none",
        "--single-branch",
        "https://github.com/folke/lazy.nvim.git",
        lazypath,
    })
end
vim.opt.runtimepath:prepend(lazypath)

-- install plugins
vim.keymap.set("n", "<Leader>e", "<Plug>(x-file-explorer)", { silent = true })
local M = {
    "nvim-telescope/telescope.nvim",
    dependencies = {
        "nvim-lua/plenary.nvim",
        "nvim-treesitter/nvim-treesitter",
    },
    config = function()
        local bufopts = { noremap = true, silent = true }
        local builtin = require("telescope.builtin")
        vim.keymap.set("n", "gb", function()
            builtin.git_bcommits({
                git_command = {
                    "git",
                    "log",
                    -- "--pretty=oneline",
                    -- "--abbrev-commit",
                    "--date=format:%y/%m/%d",
                    "--pretty=format:%C(auto) %h %ad %s",
                    "--follow",
                },
            })
        end, bufopts)
        vim.keymap.set("n", "gj", builtin.git_bcommits, bufopts)

        require("telescope").setup({})
    end,
}
local plugins = {
    M,
}
require("lazy").setup(plugins, {
    root = root .. "/plugins",
})
jamestrew commented 1 year ago

I can reproduce this.

I dug around a little bit while I don't really have a solution, my instinct is telling me that that command is not very well suited for passing the output through pipes. At least not with how telescope currently works.

I played around with this bit of code. If you do as well, you should see that, for you command, after the first stdout chunk, each subsequent chunk appears to start with a new line. The telescope code doesn't handle that well. Try it with the original command, the new line comes after the chunk is done. Maybe the telescope code should handle this better, but also maybe git is being weird.

the code ```lua local uv = vim.loop local stdin = uv.new_pipe() local stdout = uv.new_pipe() local stderr = uv.new_pipe() local handle, pid = uv.spawn("git", { args = { "log", -- "--pretty=oneline", -- "--abbrev-commit", "--date=format:%y/%m/%d", "--pretty=format:%h %ad %s", "--follow", "/tmp/testing/dotfile/nvim/.config/nvim/lua/plugins/telescope.lua", }, stdio = { stdin, stdout, stderr, }, }, function(code, signal) -- on exit print("exit code", code) print("exit signal", signal) end) print("process opened", handle, pid) stdout:read_start(function(err, data) assert(not err, err) if data then vim.print("stdout chunk", data) else vim.print("stdout end") end end) ```
keaising commented 1 year ago

Thanks for your instinct, I find a workround to solve this issue.

I create a bash script named gitlog.sh to output all content of git log in one time, so the content passed to Telescope will be processed only once, it works as my wish!

This is my script:

#!/usr/bin/env bash

# $1 is the file path from Telescope
git log --date="format:%y/%m/%d" --pretty="format:%C(auto) %h %ad %s" --follow $1 >/tmp/gitlog && cat /tmp/gitlog

And this is my Telescope config

    config = function()
        local bufopts = { noremap = true, silent = true }
        local builtin = require("telescope.builtin")
        vim.keymap.set("n", "gb", function()
            builtin.git_bcommits({
                git_command = { "/location/of/gitlog.sh" },
            })
        end, bufopts)
        vim.keymap.set("n", "gj", builtin.git_bcommits, bufopts)

        require("telescope").setup({})
    end,
keaising commented 1 year ago

@jamestrew Do you think it's necessary to keep this issue open and let's work through it to solve the problem once and for all, or do we just stop here, there's already a workround anyway, after all not all bugs have to be fixed and it's not necessarily a Telescope's bug

jamestrew commented 1 year ago

I think it's ok to leave it open. This might be something worth looking into deeper.

nicos68 commented 2 months ago

Thanks for your instinct, I find a workround to solve this issue.

I create a bash script named gitlog.sh to output all content of git log in one time, so the content passed to Telescope will be processed only once, it works as my wish!

This is my script:

#!/usr/bin/env bash

# $1 is the file path from Telescope
git log --date="format:%y/%m/%d" --pretty="format:%C(auto) %h %ad %s" --follow $1 >/tmp/gitlog && cat /tmp/gitlog

And this is my Telescope config

    config = function()
        local bufopts = { noremap = true, silent = true }
        local builtin = require("telescope.builtin")
        vim.keymap.set("n", "gb", function()
            builtin.git_bcommits({
                git_command = { "/location/of/gitlog.sh" },
            })
        end, bufopts)
        vim.keymap.set("n", "gj", builtin.git_bcommits, bufopts)

        require("telescope").setup({})
    end,

I tried your workaound, but I still get an empty window. However if I replace what’s inside of the gitlog.sh file with

git log --follow $1 >/tmp/gitlog && cat /tmp/gitlog

then I do get the result of git log in my telescope popup …

EDIT: If I just add an echo "" >> /tmp/gitlog command in the end it works

¯\_(ツ)_/¯

So the workaround becomes

git log --date="format:%y/%m/%d" --pretty="format:%C(auto) %h %ad %s" --follow $1 \
  >/tmp/gitlog \
  && echo "" >> /tmp/gitlog \
  && cat /tmp/gitlog