Skip to content

Commit

Permalink
perf(git): use 'uv.spawn' for command line IO (#70)
Browse files Browse the repository at this point in the history
* refactor(gitlinker): optimize code logic

* revert

* fix: only set key mappings when options.mappings is lua table

* perf(git): add 'uv.spawn'

* perf(git): add 'uv.spawn'

* perf(git): migrate from jobstart to uv.spawn

* refactor(git): rewrite JobReslt

* fix

* chore

* test

* chore
  • Loading branch information
linrongbin16 authored Oct 20, 2023
1 parent 9799b79 commit 35aebb7
Show file tree
Hide file tree
Showing 6 changed files with 559 additions and 87 deletions.
4 changes: 4 additions & 0 deletions .luacov
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
modules = {
["gitlinker"] = "lua/gitlinker.lua",
["gitlinker.*"] = "lua",
}
8 changes: 8 additions & 0 deletions codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
coverage:
status:
project:
default:
threshold: 90%
patch:
default:
threshold: 90%
29 changes: 14 additions & 15 deletions lua/gitlinker.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ local git = require("gitlinker.git")
local util = require("gitlinker.util")
local logger = require("gitlinker.logger")

--- @alias Configs table<any, any>
--- @type Configs
--- @alias Options table<any, any>
--- @type Options
local Defaults = {
-- print message(git host url) in command line
--
--- @type boolean
message = true,

Expand All @@ -24,8 +25,8 @@ local Defaults = {
},
},

-- regex pattern based rules
--- @type table<string, string>[]
-- pattern based rules
--- @type {[1]:table<string,string>,[2]:table<string,string>}
pattern_rules = {
{
["^git@github%.([_%.%-%w]+):([%.%-%w]+)/([_%.%-%w]+)%.git$"] = "https://github.%1/%2/%3/blob/",
Expand Down Expand Up @@ -88,10 +89,10 @@ local Defaults = {
file_log = false,
}

--- @type Configs
--- @type Options
local Configs = {}

--- @param option Configs?
--- @param option Options?
local function setup(option)
Configs = vim.tbl_deep_extend("force", Defaults, option or {})

Expand All @@ -112,7 +113,7 @@ local function setup(option)
end

-- key mapping
if key_mappings then
if type(key_mappings) == "table" then
for k, v in pairs(key_mappings) do
local opt = {
noremap = true,
Expand Down Expand Up @@ -162,8 +163,8 @@ end
local function make_link_data(range)
--- @type JobResult
local root_result = git.get_root()
if not git.result_has_out(root_result) then
git.result_print_err(root_result, "not in a git repository")
if not root_result:has_out() then
root_result:print_err("not in a git repository")
return nil
end
logger.debug(
Expand All @@ -185,9 +186,8 @@ local function make_link_data(range)

--- @type JobResult
local remote_url_result = git.get_remote_url(remote)
if not git.result_has_out(remote_url_result) then
git.result_print_err(
remote_url_result,
if not remote_url_result:has_out() then
remote_url_result:print_err(
"failed to get remote url by remote '" .. remote .. "'"
)
return nil
Expand Down Expand Up @@ -221,9 +221,8 @@ local function make_link_data(range)

--- @type JobResult
local file_in_rev_result = git.is_file_in_rev(buf_path_on_root, rev)
if git.result_has_err(file_in_rev_result) then
git.result_print_err(
file_in_rev_result,
if file_in_rev_result:has_err() then
file_in_rev_result:print_err(
"'"
.. buf_path_on_root
.. "' does not exist in remote '"
Expand Down
115 changes: 43 additions & 72 deletions lua/gitlinker/git.lua
Original file line number Diff line number Diff line change
@@ -1,31 +1,38 @@
local logger = require("gitlinker.logger")
local spawn = require("gitlinker.spawn")

--- @class JobResult
--- @field stdout string[]
--- @field stderr string[]
local JobResult = {}

--- @return JobResult
function JobResult:new()
local o = {
stdout = {},
stderr = {},
}
setmetatable(o, self)
self.__index = self
return o
end

--- @param result JobResult
--- @return boolean
local function result_has_out(result)
return result["stdout"]
and type(result["stdout"]) == "table"
and #result["stdout"] > 0
function JobResult:has_out()
return type(self.stdout) == "table" and #self.stdout > 0
end

--- @param result JobResult
--- @return boolean
local function result_has_err(result)
return result["stderr"] ~= nil
and type(result["stderr"]) == "table"
and #result["stderr"] > 0
function JobResult:has_err()
return type(self.stderr) == "table" and #self.stderr > 0
end

--- @param result JobResult
--- @param default string|nil
--- @return nil
local function result_print_err(result, default)
if result_has_err(result) and #result.stderr > 0 then
logger.err("%s", result.stderr[1])
--- @param default string
function JobResult:print_err(default)
if self:has_err() then
for _, e in ipairs(self.stderr) do
logger.err("%s", e)
end
else
logger.err("fatal: %s", default)
end
Expand All @@ -37,51 +44,19 @@ end
--- @param cwd string|nil
--- @return JobResult
local function cmd(args, cwd)
local result = { stdout = {}, stderr = {} }
local job = vim.fn.jobstart(args, {
cwd = cwd,
on_stdout = function(chanid, data, name)
logger.debug(
"|cmd.on_stdout| args(%s):%s, cwd(%s):%s, chanid(%s):%s, data(%s):%s, name(%s):%s",
vim.inspect(type(args)),
vim.inspect(args),
vim.inspect(type(cwd)),
vim.inspect(cwd),
vim.inspect(type(chanid)),
vim.inspect(chanid),
vim.inspect(type(data)),
vim.inspect(data),
vim.inspect(type(name)),
vim.inspect(name)
)
for _, line in ipairs(data) do
if string.len(line) > 0 then
table.insert(result.stdout, line)
end
end
end,
on_stderr = function(chanid, data, name)
logger.debug(
"|cmd.on_stderr| args(%s):%s, cwd(%s):%s, chanid(%s):%s, data(%s):%s, name(%s):%s",
vim.inspect(type(args)),
vim.inspect(args),
vim.inspect(type(cwd)),
vim.inspect(cwd),
vim.inspect(type(chanid)),
vim.inspect(chanid),
vim.inspect(type(data)),
vim.inspect(data),
vim.inspect(type(name)),
vim.inspect(name)
)
for _, line in ipairs(data) do
if string.len(line) > 0 then
table.insert(result.stderr, line)
end
end
end,
})
vim.fn.jobwait({ job })
local result = JobResult:new()

local sp = spawn.Spawn:make(args, function(line)
if type(line) == "string" then
table.insert(result.stdout, line)
end
end, function(line)
if type(line) == "string" then
table.insert(result.stderr, line)
end
end) --[[@as Spawn]]
sp:run()

logger.debug(
"|cmd| args(%s):%s, cwd(%s):%s, result(%s):%s",
vim.inspect(type(args)),
Expand Down Expand Up @@ -123,7 +98,7 @@ end

--- @package
--- @param revspec string|nil
--- @return string|nil
--- @return string?
local function get_rev(revspec)
local result = cmd({ "git", "rev-parse", revspec })
logger.debug(
Expand All @@ -133,7 +108,7 @@ local function get_rev(revspec)
vim.inspect(type(result)),
vim.inspect(result)
)
return result_has_out(result) and result.stdout[1] or nil
return result:has_out() and result.stdout[1] or nil
end

--- @package
Expand Down Expand Up @@ -182,7 +157,7 @@ local function has_file_changed(file, rev)
vim.inspect(type(result)),
vim.inspect(result)
)
return result_has_out(result)
return result:has_out()
end

--- @package
Expand Down Expand Up @@ -271,14 +246,14 @@ local function get_root()
return result
end

--- @return string|nil
--- @return string?
local function get_branch_remote()
-- origin/upstream
--- @type JobResult
local remote_result = get_remote()

if type(remote_result.stdout) ~= "table" or #remote_result.stdout == 0 then
result_print_err(remote_result, "git repository has no remote")
remote_result:print_err("git repository has no remote")
return nil
end

Expand All @@ -289,8 +264,8 @@ local function get_branch_remote()
-- origin/linrongbin16/add-rule2
--- @type JobResult
local upstream_branch_result = get_rev_name("@{u}")
if not result_has_out(upstream_branch_result) then
result_print_err(upstream_branch_result, "git branch has no remote")
if not upstream_branch_result:has_out() then
upstream_branch_result:print_err("git branch has no remote")
return nil
end

Expand Down Expand Up @@ -324,11 +299,7 @@ local function get_branch_remote()
return nil
end

--- @type table<string, function>
local M = {
result_has_out = result_has_out,
result_has_err = result_has_err,
result_print_err = result_print_err,
get_root = get_root,
get_remote_url = get_remote_url,
is_file_in_rev = is_file_in_rev,
Expand Down
Loading

0 comments on commit 35aebb7

Please sign in to comment.