linrongbin16 / gitlinker.nvim

Maintained fork of ruifm's gitlinker, refactored with bug fixes, ssh aliases, blame support and other improvements.
GNU General Public License v3.0
163 stars 9 forks source link

Feature: use upstream remote for url generation #242

Closed tvsfx closed 5 months ago

tvsfx commented 5 months ago

First off, thank you for the plug-in! It has saved me a lot of time already :)

As far as I can tell, gitlinker just picks the first remote from the list of remotes when generating the URL (unless a remote is provided as part of the options). The original gitlinker plugin by ruifm seems to use the identity of the upstream to make this choice (here). Is there a way to emulate this behavior in this plugin? It is usually the desired behavior for me.

linrongbin16 commented 5 months ago

hi @tvsfx ,

add remote=upstream for GitLink command, when you have multiple remotes.

tvsfx commented 5 months ago

This works, but is not ideal because I have to figure out what the name of upstream is for the current repository. I could run the following under the repo's path as part of the keybind: git rev-parse --abbrev-ref @{u}, but I just wanted to make sure there is no way to do this inside gitlinker.

linrongbin16 commented 5 months ago

hi @tvsfx ,

when there are multiple remotes, gitlinker will not know which one to choose.

tvsfx commented 5 months ago

I see. However, I think picking the remote corresponding to the upstream of the current branch should be a better default than just picking the first remote (since afaict, the output of git remote that gitlinker relies upon is just alphabetically sorted). I went ahead and implemented this, reusing some code from ruifm/gitlinker, and it seems to work (I use origin as a fallback remote in case no upstream remote is found for the current branch). In case it could be of use, my config for gitlinker now looks as follows:

-- Get git path for buffer
function get_git_root()
    local dot_git_path = vim.fn.finddir(".git", ".;")
    return vim.fn.fnamemodify(dot_git_path, ":h")
end

-- from `ruifm/gitlinker`: wrap the git command to do the right thing always
function git(args, cwd)
  local job = require("plenary.job")
  local output
  local p = job:new({
    command = "git",
    args = args,
    cwd = cwd or get_git_root(),
  })
  p:after_success(function(j)
    output = j:result()
  end)
  p:sync()
  return output or {}
end

-- from `ruifm/gitlinker`: retrieve name of upstream remote/branch
local function get_rev_name(revspec)
  return git({ "rev-parse", "--abbrev-ref", revspec })[1]
end

-- retrieve name of remote, using `origin` as a fallback
local function get_remote()
    local upstream_branch = get_rev_name("@{u}")
    if not upstream_branch then
        return "origin"
    else
        -- from `ruifm/gitlinker`: parse remote
        local allowed_chars = "[_%-%w%.]+"
        local remote_from_upstream_branch = upstream_branch:match(
            "^(" .. allowed_chars .. ")%/"
        )
        return remote_from_upstream_branch
    end
end

return {
    "linrongbin16/gitlinker.nvim",
    cmd = "GitLink",
    dependencies = { "nvim-lua/plenary.nvim" },
    opts = {},
    keys = {
      { "<leader>gy", function()
            vim.cmd { cmd = "GitLink", args = { "remote=" .. get_remote() } }
        end
        , mode = { "n", "v" }, desc = "Yank git link" },
      { "<leader>gY", function()
            vim.cmd { cmd = "GitLink", args = { "remote=" .. get_remote() }, bang = true}
        end
        , mode = { "n", "v" }, desc = "Open git link" },
    },
}
linrongbin16 commented 5 months ago

hi @tvsfx,

your configs looks really good, I think I will close this ticket now.