Skip to content

Commit

Permalink
fix(path): resolve symlink in Windows (#75)
Browse files Browse the repository at this point in the history
* fix(logger): remove 'error!' prefix

* fix(git): fix command line running cwd

* refactor(util): rewrite path relative, normalize util functions

* fix(path): fix symlink resolve in Windows

* refactor(lint): fix typecheck

* refactor(lint): fix typecheck

* test(spawn): fix test cases

* fix(spawn): set 'cwd' options
  • Loading branch information
linrongbin16 committed Oct 20, 2023
1 parent 9100497 commit b292a4f
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 91 deletions.
4 changes: 2 additions & 2 deletions lua/gitlinker.lua
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ local function make_link_data(range)
vim.inspect(rev)
)

local buf_path_on_root = util.relative_path(root)
local buf_path_on_root = util.path_relative(root) --[[@as string]]
logger.debug(
"|make_link_data| root(%s):%s, buf_path_on_root(%s):%s",
vim.inspect(type(root)),
Expand All @@ -215,7 +215,7 @@ local function make_link_data(range)
vim.inspect(file_in_rev_result)
)

local buf_path_on_cwd = util.relative_path()
local buf_path_on_cwd = util.path_relative() --[[@as string]]
logger.debug(
"|make_link_data| buf_path_on_cwd:%s",
vim.inspect(buf_path_on_cwd)
Expand Down
38 changes: 17 additions & 21 deletions lua/gitlinker/git.lua
Original file line number Diff line number Diff line change
Expand Up @@ -41,29 +41,30 @@ end
-- wrap the git command to do the right thing always
--- @package
--- @param args string[]
--- @param cwd string|nil
--- @param cwd string?
--- @return JobResult
local function cmd(args, cwd)
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]]
local sp = spawn.Spawn:make(args, {
cwd = cwd or vim.fn.getcwd(),
on_stdout = function(line)
if type(line) == "string" then
table.insert(result.stdout, line)
end
end,
on_stderr = 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)),
"|git.cmd| args:%s, cwd:%s, result:%s",
vim.inspect(args),
vim.inspect(type(cwd)),
vim.inspect(cwd),
vim.inspect(type(result)),
vim.inspect(result)
)
return result
Expand Down Expand Up @@ -102,10 +103,8 @@ end
local function _get_rev(revspec)
local result = cmd({ "git", "rev-parse", revspec })
logger.debug(
"|git._get_rev| revspec(%s):%s, result(%s):%s",
vim.inspect(type(revspec)),
"|git._get_rev| revspec:%s, result:%s",
vim.inspect(revspec),
vim.inspect(type(result)),
vim.inspect(result)
)
return result:has_out() and result.stdout[1] or nil
Expand Down Expand Up @@ -232,12 +231,9 @@ local function get_root()
local buf_dir = vim.fn.fnamemodify(buf_path, ":p:h")
local result = cmd({ "git", "rev-parse", "--show-toplevel" }, buf_dir)
logger.debug(
"|git.get_root| buf_path(%s):%s, buf_dir(%s):%s, result(%s):%s",
vim.inspect(type(buf_path)),
"|git.get_root| buf_path:%s, buf_dir:%s, result:%s",
vim.inspect(buf_path),
vim.inspect(type(buf_dir)),
vim.inspect(buf_dir),
vim.inspect(type(result)),
vim.inspect(result)
)
if not result:has_out() then
Expand Down
14 changes: 7 additions & 7 deletions lua/gitlinker/logger.lua
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,15 @@ local function log(level, msg)
local msg_lines = vim.split(msg, "\n", { plain = true })
if Configs.console_log and level >= LogLevels.INFO then
local msg_chunks = {}
local prefix = ""
if level == LogLevels.ERROR then
prefix = "error! "
elseif level == LogLevels.WARN then
prefix = "warning! "
end
-- local prefix = ""
-- if level == LogLevels.ERROR then
-- prefix = "error! "
-- elseif level == LogLevels.WARN then
-- prefix = "warning! "
-- end
for _, line in ipairs(msg_lines) do
table.insert(msg_chunks, {
string.format("[gitlinker] %s%s", prefix, line),
string.format("[gitlinker] %s", --[[prefix,]] line),
LogHighlights[level],
})
end
Expand Down
13 changes: 7 additions & 6 deletions lua/gitlinker/spawn.lua
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ end
--- @alias SpawnLineConsumer fun(line:string):any
--- @class Spawn
--- @field cmds string[]
--- @field cwd string?
--- @field fn_out_line_consumer SpawnLineConsumer
--- @field fn_err_line_consumer SpawnLineConsumer
--- @field out_pipe uv_pipe_t
Expand All @@ -81,10 +82,9 @@ local function dummy_stderr_line_consumer(line)
end

--- @param cmds string[]
--- @param fn_out_line_consumer SpawnLineConsumer
--- @param fn_err_line_consumer SpawnLineConsumer?
--- @param opts {on_stdout:SpawnLineConsumer,on_stderr:SpawnLineConsumer?,cwd:string?}
--- @return Spawn?
function Spawn:make(cmds, fn_out_line_consumer, fn_err_line_consumer)
function Spawn:make(cmds, opts)
local out_pipe = vim.loop.new_pipe(false) --[[@as uv_pipe_t]]
local err_pipe = vim.loop.new_pipe(false) --[[@as uv_pipe_t]]
if not out_pipe or not err_pipe then
Expand All @@ -93,9 +93,9 @@ function Spawn:make(cmds, fn_out_line_consumer, fn_err_line_consumer)

local o = {
cmds = cmds,
fn_out_line_consumer = fn_out_line_consumer,
fn_err_line_consumer = fn_err_line_consumer
or dummy_stderr_line_consumer,
cwd = opts.cwd or vim.fn.getcwd(),
fn_out_line_consumer = opts.on_stdout,
fn_err_line_consumer = opts.on_stderr or dummy_stderr_line_consumer,
out_pipe = out_pipe,
err_pipe = err_pipe,
out_buffer = nil,
Expand Down Expand Up @@ -228,6 +228,7 @@ end
function Spawn:run()
self.process_handle, self.process_id = vim.loop.spawn(self.cmds[1], {
args = vim.list_slice(self.cmds, 2),
cwd = self.cwd,
stdio = { nil, self.out_pipe, self.err_pipe },
hide = true,
-- verbatim = true,
Expand Down
85 changes: 43 additions & 42 deletions lua/gitlinker/util.lua
Original file line number Diff line number Diff line change
@@ -1,56 +1,56 @@
local logger = require("gitlinker.logger")

-- normalize path slash from '\\' to '/'
--- @param p string
--- @return string
local function path_normalize(p)
local result = vim.fn.expand(p)
if string.match(result, [[\\]]) then
result = string.gsub(result, [[\\]], [[/]])
end
if string.match(result, [[\]]) then
result = string.gsub(result, [[\]], [[/]])
end
return vim.trim(result)
end

--- @param cwd string?
--- @return string?
local function relative_path(cwd)
logger.debug(
"|util.relative_path| cwd1(%s):%s",
vim.inspect(type(cwd)),
vim.inspect(cwd)
)

local buf_path = vim.api.nvim_buf_get_name(0)
if cwd == nil or string.len(cwd) <= 0 then
cwd = vim.fn.getcwd()
end
-- get real path from possibly symlink
local function path_relative(cwd)
cwd = cwd or vim.fn.getcwd()
cwd = vim.fn.resolve(cwd)
-- normalize path slash from '\\' to '/'
if cwd:find("\\") then
cwd = cwd:gsub("\\\\", "/")
cwd = cwd:gsub("\\", "/")
end
if buf_path:find("\\") then
buf_path = buf_path:gsub("\\\\", "/")
buf_path = buf_path:gsub("\\", "/")
end
cwd = path_normalize(cwd)

local bufpath = vim.api.nvim_buf_get_name(0)
bufpath = vim.fn.resolve(bufpath)
bufpath = path_normalize(bufpath)

logger.debug(
"|util.relative_path| buf_path(%s):%s, cwd(%s):%s",
vim.inspect(type(buf_path)),
vim.inspect(buf_path),
vim.inspect(type(cwd)),
vim.inspect(cwd)
"|util.path_relative| enter, cwd:%s, bufpath:%s",
vim.inspect(cwd),
vim.inspect(bufpath)
)

local relpath = nil
if buf_path:sub(1, #cwd) == cwd then
relpath = buf_path:sub(#cwd + 1, -1)
if relpath:sub(1, 1) == "/" or relpath:sub(1, 1) == "\\" then
relpath = relpath:sub(2, -1)
local result = nil
if
string.len(bufpath) >= string.len(cwd)
and bufpath:sub(1, #cwd) == cwd
then
result = bufpath:sub(#cwd + 1)
if result:sub(1, 1) == "/" or result:sub(1, 1) == "\\" then
result = result:sub(2)
end
end
logger.debug(
"|util.relative_path| relpath(%s):%s",
vim.inspect(type(relpath)),
vim.inspect(relpath)
)
return relpath
logger.debug("|util.path_relative| result:%s", vim.inspect(result))
return result
end

--- @param m string
--- @return boolean
local function is_visual_mode(m)
return type(m) == "string" and m:upper() == "V"
or m:upper() == "CTRL-V"
or m:upper() == "<C-V>"
return type(m) == "string" and string.upper(m) == "V"
or string.upper(m) == "CTRL-V"
or string.upper(m) == "<C-V>"
or m == "\22"
end

Expand All @@ -76,9 +76,10 @@ local function line_range()
return { lstart = lstart, lend = lend }
end

--- @type table<string, function>
local M = {
relative_path = relative_path,
path_normalize = path_normalize,
path_relative = path_relative,
is_visual_mode = is_visual_mode,
line_range = line_range,
}

Expand Down
50 changes: 37 additions & 13 deletions test/spawn_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,10 @@ describe("spawn", function()
end)
describe("[Spawn]", function()
it("open", function()
local sp = spawn.Spawn:make({ "cat", "README.md" }, function() end) --[[@as Spawn]]
local sp = spawn.Spawn:make(
{ "cat", "README.md" },
{ on_stdout = function() end }
) --[[@as Spawn]]
assert_eq(type(sp), "table")
assert_eq(type(sp.cmds), "table")
assert_eq(#sp.cmds, 2)
Expand All @@ -69,7 +72,10 @@ describe("spawn", function()
assert_eq(line, lines[i])
i = i + 1
end
local sp = spawn.Spawn:make({ "cat", "README.md" }, process_line) --[[@as Spawn]]
local sp = spawn.Spawn:make(
{ "cat", "README.md" },
{ on_stdout = process_line }
) --[[@as Spawn]]
local pos = sp:_consume_line(content, process_line)
if pos <= #content then
local line = content:sub(pos, #content)
Expand All @@ -87,7 +93,10 @@ describe("spawn", function()
assert_eq(line, lines[i])
i = i + 1
end
local sp = spawn.Spawn:make({ "cat", "README.md" }, process_line) --[[@as Spawn]]
local sp = spawn.Spawn:make(
{ "cat", "README.md" },
{ on_stdout = process_line }
) --[[@as Spawn]]
local content_splits =
vim.split(content, "\n", { plain = true, trimempty = false })
for j, splits in ipairs(content_splits) do
Expand All @@ -110,7 +119,10 @@ describe("spawn", function()
assert_eq(line, lines[i])
i = i + 1
end
local sp = spawn.Spawn:make({ "cat", "README.md" }, process_line) --[[@as Spawn]]
local sp = spawn.Spawn:make(
{ "cat", "README.md" },
{ on_stdout = process_line }
) --[[@as Spawn]]
local content_splits =
vim.split(content, " ", { plain = true, trimempty = false })
for j, splits in ipairs(content_splits) do
Expand All @@ -136,8 +148,10 @@ describe("spawn", function()
assert_eq(line, lines[i])
i = i + 1
end
local sp =
spawn.Spawn:make({ "cat", "README.md" }, process_line) --[[@as Spawn]]
local sp = spawn.Spawn:make(
{ "cat", "README.md" },
{ on_stdout = process_line }
) --[[@as Spawn]]
local content_splits = vim.split(
content,
lower_char,
Expand Down Expand Up @@ -165,8 +179,10 @@ describe("spawn", function()
assert_eq(line, lines[i])
i = i + 1
end
local sp =
spawn.Spawn:make({ "cat", "README.md" }, process_line) --[[@as Spawn]]
local sp = spawn.Spawn:make(
{ "cat", "README.md" },
{ on_stdout = process_line }
) --[[@as Spawn]]
local content_splits = vim.split(
content,
upper_char,
Expand All @@ -183,7 +199,10 @@ describe("spawn", function()
end)
end
it("stderr", function()
local sp = spawn.Spawn:make({ "cat", "README.md" }, function() end) --[[@as Spawn]]
local sp = spawn.Spawn:make(
{ "cat", "README.md" },
{ on_stdout = function() end }
) --[[@as Spawn]]
sp:_on_stderr(nil, nil)
assert_true(sp.err_pipe:is_closing())
end)
Expand All @@ -198,7 +217,10 @@ describe("spawn", function()
i = i + 1
end

local sp = spawn.Spawn:make({ "cat", "README.md" }, process_line) --[[@as Spawn]]
local sp = spawn.Spawn:make(
{ "cat", "README.md" },
{ on_stdout = process_line }
) --[[@as Spawn]]
sp:run()
end)
it("iterate on lua/gitlinker.lua", function()
Expand All @@ -212,14 +234,16 @@ describe("spawn", function()
i = i + 1
end

local sp =
spawn.Spawn:make({ "cat", "lua/gitlinker.lua" }, process_line) --[[@as Spawn]]
local sp = spawn.Spawn:make(
{ "cat", "lua/gitlinker.lua" },
{ on_stdout = process_line }
) --[[@as Spawn]]
sp:run()
end)
it("close handle", function()
local sp = spawn.Spawn:make(
{ "cat", "lua/gitlinker.lua" },
function() end
{ on_stdout = function() end }
) --[[@as Spawn]]
sp:run()
assert_true(sp.process_handle ~= nil)
Expand Down

0 comments on commit b292a4f

Please sign in to comment.