Skip to content

Commit 35aebb7

Browse files
authored
perf(git): use 'uv.spawn' for command line IO (ruifm#70)
* 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
1 parent 9799b79 commit 35aebb7

File tree

6 files changed

+559
-87
lines changed

6 files changed

+559
-87
lines changed

.luacov

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
modules = {
2+
["gitlinker"] = "lua/gitlinker.lua",
3+
["gitlinker.*"] = "lua",
4+
}

codecov.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
coverage:
2+
status:
3+
project:
4+
default:
5+
threshold: 90%
6+
patch:
7+
default:
8+
threshold: 90%

lua/gitlinker.lua

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ local git = require("gitlinker.git")
22
local util = require("gitlinker.util")
33
local logger = require("gitlinker.logger")
44

5-
--- @alias Configs table<any, any>
6-
--- @type Configs
5+
--- @alias Options table<any, any>
6+
--- @type Options
77
local Defaults = {
88
-- print message(git host url) in command line
9+
--
910
--- @type boolean
1011
message = true,
1112

@@ -24,8 +25,8 @@ local Defaults = {
2425
},
2526
},
2627

27-
-- regex pattern based rules
28-
--- @type table<string, string>[]
28+
-- pattern based rules
29+
--- @type {[1]:table<string,string>,[2]:table<string,string>}
2930
pattern_rules = {
3031
{
3132
["^git@github%.([_%.%-%w]+):([%.%-%w]+)/([_%.%-%w]+)%.git$"] = "https://github.%1/%2/%3/blob/",
@@ -88,10 +89,10 @@ local Defaults = {
8889
file_log = false,
8990
}
9091

91-
--- @type Configs
92+
--- @type Options
9293
local Configs = {}
9394

94-
--- @param option Configs?
95+
--- @param option Options?
9596
local function setup(option)
9697
Configs = vim.tbl_deep_extend("force", Defaults, option or {})
9798

@@ -112,7 +113,7 @@ local function setup(option)
112113
end
113114

114115
-- key mapping
115-
if key_mappings then
116+
if type(key_mappings) == "table" then
116117
for k, v in pairs(key_mappings) do
117118
local opt = {
118119
noremap = true,
@@ -162,8 +163,8 @@ end
162163
local function make_link_data(range)
163164
--- @type JobResult
164165
local root_result = git.get_root()
165-
if not git.result_has_out(root_result) then
166-
git.result_print_err(root_result, "not in a git repository")
166+
if not root_result:has_out() then
167+
root_result:print_err("not in a git repository")
167168
return nil
168169
end
169170
logger.debug(
@@ -185,9 +186,8 @@ local function make_link_data(range)
185186

186187
--- @type JobResult
187188
local remote_url_result = git.get_remote_url(remote)
188-
if not git.result_has_out(remote_url_result) then
189-
git.result_print_err(
190-
remote_url_result,
189+
if not remote_url_result:has_out() then
190+
remote_url_result:print_err(
191191
"failed to get remote url by remote '" .. remote .. "'"
192192
)
193193
return nil
@@ -221,9 +221,8 @@ local function make_link_data(range)
221221

222222
--- @type JobResult
223223
local file_in_rev_result = git.is_file_in_rev(buf_path_on_root, rev)
224-
if git.result_has_err(file_in_rev_result) then
225-
git.result_print_err(
226-
file_in_rev_result,
224+
if file_in_rev_result:has_err() then
225+
file_in_rev_result:print_err(
227226
"'"
228227
.. buf_path_on_root
229228
.. "' does not exist in remote '"

lua/gitlinker/git.lua

Lines changed: 43 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,38 @@
11
local logger = require("gitlinker.logger")
2+
local spawn = require("gitlinker.spawn")
23

34
--- @class JobResult
45
--- @field stdout string[]
56
--- @field stderr string[]
7+
local JobResult = {}
8+
9+
--- @return JobResult
10+
function JobResult:new()
11+
local o = {
12+
stdout = {},
13+
stderr = {},
14+
}
15+
setmetatable(o, self)
16+
self.__index = self
17+
return o
18+
end
619

7-
--- @param result JobResult
820
--- @return boolean
9-
local function result_has_out(result)
10-
return result["stdout"]
11-
and type(result["stdout"]) == "table"
12-
and #result["stdout"] > 0
21+
function JobResult:has_out()
22+
return type(self.stdout) == "table" and #self.stdout > 0
1323
end
1424

15-
--- @param result JobResult
1625
--- @return boolean
17-
local function result_has_err(result)
18-
return result["stderr"] ~= nil
19-
and type(result["stderr"]) == "table"
20-
and #result["stderr"] > 0
26+
function JobResult:has_err()
27+
return type(self.stderr) == "table" and #self.stderr > 0
2128
end
2229

23-
--- @param result JobResult
24-
--- @param default string|nil
25-
--- @return nil
26-
local function result_print_err(result, default)
27-
if result_has_err(result) and #result.stderr > 0 then
28-
logger.err("%s", result.stderr[1])
30+
--- @param default string
31+
function JobResult:print_err(default)
32+
if self:has_err() then
33+
for _, e in ipairs(self.stderr) do
34+
logger.err("%s", e)
35+
end
2936
else
3037
logger.err("fatal: %s", default)
3138
end
@@ -37,51 +44,19 @@ end
3744
--- @param cwd string|nil
3845
--- @return JobResult
3946
local function cmd(args, cwd)
40-
local result = { stdout = {}, stderr = {} }
41-
local job = vim.fn.jobstart(args, {
42-
cwd = cwd,
43-
on_stdout = function(chanid, data, name)
44-
logger.debug(
45-
"|cmd.on_stdout| args(%s):%s, cwd(%s):%s, chanid(%s):%s, data(%s):%s, name(%s):%s",
46-
vim.inspect(type(args)),
47-
vim.inspect(args),
48-
vim.inspect(type(cwd)),
49-
vim.inspect(cwd),
50-
vim.inspect(type(chanid)),
51-
vim.inspect(chanid),
52-
vim.inspect(type(data)),
53-
vim.inspect(data),
54-
vim.inspect(type(name)),
55-
vim.inspect(name)
56-
)
57-
for _, line in ipairs(data) do
58-
if string.len(line) > 0 then
59-
table.insert(result.stdout, line)
60-
end
61-
end
62-
end,
63-
on_stderr = function(chanid, data, name)
64-
logger.debug(
65-
"|cmd.on_stderr| args(%s):%s, cwd(%s):%s, chanid(%s):%s, data(%s):%s, name(%s):%s",
66-
vim.inspect(type(args)),
67-
vim.inspect(args),
68-
vim.inspect(type(cwd)),
69-
vim.inspect(cwd),
70-
vim.inspect(type(chanid)),
71-
vim.inspect(chanid),
72-
vim.inspect(type(data)),
73-
vim.inspect(data),
74-
vim.inspect(type(name)),
75-
vim.inspect(name)
76-
)
77-
for _, line in ipairs(data) do
78-
if string.len(line) > 0 then
79-
table.insert(result.stderr, line)
80-
end
81-
end
82-
end,
83-
})
84-
vim.fn.jobwait({ job })
47+
local result = JobResult:new()
48+
49+
local sp = spawn.Spawn:make(args, function(line)
50+
if type(line) == "string" then
51+
table.insert(result.stdout, line)
52+
end
53+
end, function(line)
54+
if type(line) == "string" then
55+
table.insert(result.stderr, line)
56+
end
57+
end) --[[@as Spawn]]
58+
sp:run()
59+
8560
logger.debug(
8661
"|cmd| args(%s):%s, cwd(%s):%s, result(%s):%s",
8762
vim.inspect(type(args)),
@@ -123,7 +98,7 @@ end
12398

12499
--- @package
125100
--- @param revspec string|nil
126-
--- @return string|nil
101+
--- @return string?
127102
local function get_rev(revspec)
128103
local result = cmd({ "git", "rev-parse", revspec })
129104
logger.debug(
@@ -133,7 +108,7 @@ local function get_rev(revspec)
133108
vim.inspect(type(result)),
134109
vim.inspect(result)
135110
)
136-
return result_has_out(result) and result.stdout[1] or nil
111+
return result:has_out() and result.stdout[1] or nil
137112
end
138113

139114
--- @package
@@ -182,7 +157,7 @@ local function has_file_changed(file, rev)
182157
vim.inspect(type(result)),
183158
vim.inspect(result)
184159
)
185-
return result_has_out(result)
160+
return result:has_out()
186161
end
187162

188163
--- @package
@@ -271,14 +246,14 @@ local function get_root()
271246
return result
272247
end
273248

274-
--- @return string|nil
249+
--- @return string?
275250
local function get_branch_remote()
276251
-- origin/upstream
277252
--- @type JobResult
278253
local remote_result = get_remote()
279254

280255
if type(remote_result.stdout) ~= "table" or #remote_result.stdout == 0 then
281-
result_print_err(remote_result, "git repository has no remote")
256+
remote_result:print_err("git repository has no remote")
282257
return nil
283258
end
284259

@@ -289,8 +264,8 @@ local function get_branch_remote()
289264
-- origin/linrongbin16/add-rule2
290265
--- @type JobResult
291266
local upstream_branch_result = get_rev_name("@{u}")
292-
if not result_has_out(upstream_branch_result) then
293-
result_print_err(upstream_branch_result, "git branch has no remote")
267+
if not upstream_branch_result:has_out() then
268+
upstream_branch_result:print_err("git branch has no remote")
294269
return nil
295270
end
296271

@@ -324,11 +299,7 @@ local function get_branch_remote()
324299
return nil
325300
end
326301

327-
--- @type table<string, function>
328302
local M = {
329-
result_has_out = result_has_out,
330-
result_has_err = result_has_err,
331-
result_print_err = result_print_err,
332303
get_root = get_root,
333304
get_remote_url = get_remote_url,
334305
is_file_in_rev = is_file_in_rev,

0 commit comments

Comments
 (0)