From f3ed1a78b36af10a925a9dfa578ffc76bb6b75cb Mon Sep 17 00:00:00 2001 From: med8bra Date: Sat, 6 Jul 2024 19:06:43 +0100 Subject: [PATCH] fix(lazygit): improve git browse --- lua/lazyvim/config/options.lua | 10 +++++++ lua/lazyvim/util/lazygit.lua | 54 ++++++++++++++++++++++++++++++++-- tests/util/lazygit_spec.lua | 33 +++++++++++++++++++++ 3 files changed, 94 insertions(+), 3 deletions(-) create mode 100644 tests/util/lazygit_spec.lua diff --git a/lua/lazyvim/config/options.lua b/lua/lazyvim/config/options.lua index 5c66966a..7f9f2c21 100644 --- a/lua/lazyvim/config/options.lua +++ b/lua/lazyvim/config/options.lua @@ -31,6 +31,16 @@ vim.g.lazyvim_statuscolumn = { folds_githl = false, -- highlight fold sign with git sign color } +-- URL Templates for git browse by host, with given placeholders +-- * owner: git repo owner +-- * repo: git repo name +vim.g.lazygit_git_browse = { + ["azure.com"] = "https://dev.azure.com/${owner}/_git/${repo}", + ["bitbucket.org"] = "https://bitbucket.org/${owner}/${repo}", + ["github.com"] = "https://github.com/${owner}/${repo}", + ["gitlab.com"] = "https://gitlab.com/${owner}/${repo}", +} + -- Optionally setup the terminal to use -- This sets `vim.o.shell` and does some additional configuration for: -- * pwsh diff --git a/lua/lazyvim/util/lazygit.lua b/lua/lazyvim/util/lazygit.lua index 2e030cb6..96236b23 100644 --- a/lua/lazyvim/util/lazygit.lua +++ b/lua/lazyvim/util/lazygit.lua @@ -159,17 +159,65 @@ function M.blame_line(opts) return require("lazy.util").float_cmd(cmd, opts) end +---@class GitRemote +---@field host string +---@field owner string +---@field repo string +---@field scheme string + +---@param url string +---@return GitRemote +function M.parse_remote_url(url) + local scheme, host, owner, repo + scheme = "ssh" + -- handle ssh format: user@host:path/repo.git + _, host, owner, repo = url:match("^([^@]+)@([^:]+):(.+)/([^/]+)$") + -- handle http(s) format: scheme://host[:port]/path/repo.git + if not host then + scheme, host, _, owner, repo = url:match("^(%w+)://([^:/]+):?(%d*)(.*)/([^/]+)$") + end + + -- handle azure.com v3/ prefix + if host and host:sub(-#"azure.com") == "azure.com" then + owner = owner:gsub("^v3/", "") + end + + return { + host = host, + owner = owner, + repo = repo, + scheme = scheme, + } +end + function M.browse() local lines = require("lazy.manage.process").exec({ "git", "remote", "-v" }) local remotes = {} ---@type {name:string, url:string}[] + local git_browse_urls = vim.g.lazygit_git_browse or {} + + local function get_remote_template(remote_host) + for host, browse_url in pairs(git_browse_urls) do + if remote_host:sub(-#host) == host then + return browse_url + end + end + end for _, line in ipairs(lines) do local name, url = line:match("(%S+)%s+(%S+)%s+%(fetch%)") if name and url then - if url:find("git@") == 1 then - url = url:gsub("git@(%S+):", "https://%1/"):gsub(".git$", "") + local remote = M.parse_remote_url(url) + local git_browse_url = get_remote_template(remote.host) + if git_browse_url then + local browse_url = git_browse_url:gsub("($%b{})", function(m) + return remote[m:sub(3, -2)] or m + end) + + table.insert(remotes, { + name = name, + url = browse_url, + }) end - table.insert(remotes, { name = name, url = url }) end end diff --git a/tests/util/lazygit_spec.lua b/tests/util/lazygit_spec.lua new file mode 100644 index 00000000..40858381 --- /dev/null +++ b/tests/util/lazygit_spec.lua @@ -0,0 +1,33 @@ +---@module "luassert" + +local LazyVim = require("lazyvim.util") + +local git_remotes_cases = { + ["https://github.com/lazyvim/lazyvim.git"] = { + scheme = "https", + host = "github.com", + owner = "lazyvim", + repo = "lazyvim.git", + }, + ["git@github.com/lazyvim/lazyvim"] = { + scheme = "ssh", + host = "github.com", + owner = "lazyvim", + repo = "lazyvim", + }, + ["git@ssh.dev.azure.com:v3/neovim-org/owner/repo"] = { + scheme = "ssh", + host = "ssh.dev.azure.com", + owner = "neovim-org/owner", + repo = "repo", + }, +} + +describe("util.lazygit", function() + it("should parse git remotes", function() + for url, expected_remote in pairs(git_remotes_cases) do + local remote = LazyVim.lazygit.parse_remote_url(url) + assert.are.equal(expected_remote, remote) + end + end) +end)