refactor(git): move porcelain parsing into repo.lua
This commit is contained in:
+122
-12
@@ -19,6 +19,25 @@ end
|
||||
---@field log_max_count integer?
|
||||
---@field pending_content string?
|
||||
|
||||
---@class ow.Git.StatusEntry
|
||||
---@field section "Untracked"|"Unstaged"|"Staged"|"Unmerged"
|
||||
---@field x string
|
||||
---@field y string
|
||||
---@field path string
|
||||
---@field orig string?
|
||||
|
||||
---@class ow.Git.BranchInfo
|
||||
---@field head string?
|
||||
---@field upstream string?
|
||||
---@field ahead integer
|
||||
---@field behind integer
|
||||
|
||||
---@class ow.Git.PorcelainGroups
|
||||
---@field Untracked ow.Git.StatusEntry[]
|
||||
---@field Unstaged ow.Git.StatusEntry[]
|
||||
---@field Staged ow.Git.StatusEntry[]
|
||||
---@field Unmerged ow.Git.StatusEntry[]
|
||||
|
||||
---@class ow.Git.Repo
|
||||
---@field gitdir string
|
||||
---@field worktree string
|
||||
@@ -30,6 +49,23 @@ end
|
||||
local Repo = {}
|
||||
Repo.__index = Repo
|
||||
|
||||
---@param line string
|
||||
---@return string x, string y, string path, string? orig
|
||||
local function parse_porcelain_line(line)
|
||||
local x = line:sub(1, 1)
|
||||
local y = line:sub(2, 2)
|
||||
local rest = line:sub(4)
|
||||
local orig
|
||||
if x == "R" or x == "C" or y == "R" or y == "C" then
|
||||
local arrow = rest:find(" -> ", 1, true)
|
||||
if arrow then
|
||||
orig = rest:sub(1, arrow - 1)
|
||||
rest = rest:sub(arrow + 4)
|
||||
end
|
||||
end
|
||||
return x, y, rest, orig
|
||||
end
|
||||
|
||||
---@param r ow.Git.Repo
|
||||
local function do_refresh(r)
|
||||
vim.system(
|
||||
@@ -47,18 +83,9 @@ local function do_refresh(r)
|
||||
if obj.code == 0 then
|
||||
for line in (obj.stdout or ""):gmatch("[^\r\n]+") do
|
||||
if line:sub(1, 2) ~= "##" then
|
||||
local code = line:sub(1, 2)
|
||||
local x = code:sub(1, 1)
|
||||
local y = code:sub(2, 2)
|
||||
local path_part = line:sub(4)
|
||||
if x == "R" or x == "C" or y == "R" or y == "C" then
|
||||
local arrow = path_part:find(" -> ", 1, true)
|
||||
if arrow then
|
||||
path_part = path_part:sub(arrow + 4)
|
||||
end
|
||||
end
|
||||
statuses[vim.fs.joinpath(r.worktree, path_part)] =
|
||||
status.format(code)
|
||||
local x, y, path = parse_porcelain_line(line)
|
||||
statuses[vim.fs.joinpath(r.worktree, path)] =
|
||||
status.format(x .. y)
|
||||
end
|
||||
end
|
||||
else
|
||||
@@ -392,4 +419,87 @@ function M.stop_all()
|
||||
end
|
||||
end
|
||||
|
||||
---@param line string
|
||||
---@return ow.Git.BranchInfo
|
||||
function M.parse_branch_line(line)
|
||||
local info = { ahead = 0, behind = 0 }
|
||||
local content = line:sub(4)
|
||||
local arrow = content:find("...", 1, true)
|
||||
if not arrow then
|
||||
info.head = content
|
||||
return info
|
||||
end
|
||||
info.head = content:sub(1, arrow - 1)
|
||||
local rest = content:sub(arrow + 3)
|
||||
local bracket = rest:find(" %[")
|
||||
if not bracket then
|
||||
info.upstream = rest
|
||||
return info
|
||||
end
|
||||
info.upstream = rest:sub(1, bracket - 1)
|
||||
local inside = rest:match("%[([^%]]+)%]")
|
||||
if inside then
|
||||
info.ahead = (tonumber(inside:match("ahead (%d+)")) or 0) --[[@as integer]]
|
||||
info.behind = (tonumber(inside:match("behind (%d+)")) or 0) --[[@as integer]]
|
||||
end
|
||||
return info
|
||||
end
|
||||
|
||||
---@param stdout string
|
||||
---@return ow.Git.BranchInfo, ow.Git.PorcelainGroups
|
||||
function M.parse_porcelain(stdout)
|
||||
local branch = { ahead = 0, behind = 0 }
|
||||
---@type ow.Git.PorcelainGroups
|
||||
local groups = {
|
||||
Untracked = {},
|
||||
Unstaged = {},
|
||||
Staged = {},
|
||||
Unmerged = {},
|
||||
}
|
||||
for line in stdout:gmatch("[^\r\n]+") do
|
||||
if line:sub(1, 2) == "##" then
|
||||
branch = M.parse_branch_line(line)
|
||||
else
|
||||
local x, y, path, orig = parse_porcelain_line(line)
|
||||
if x == "?" and y == "?" then
|
||||
table.insert(groups.Untracked, {
|
||||
section = "Untracked",
|
||||
x = x,
|
||||
y = y,
|
||||
path = path,
|
||||
orig = orig,
|
||||
})
|
||||
elseif status.UNMERGED[x .. y] then
|
||||
table.insert(groups.Unmerged, {
|
||||
section = "Unmerged",
|
||||
x = x,
|
||||
y = y,
|
||||
path = path,
|
||||
orig = orig,
|
||||
})
|
||||
else
|
||||
if x ~= " " then
|
||||
table.insert(groups.Staged, {
|
||||
section = "Staged",
|
||||
x = x,
|
||||
y = y,
|
||||
path = path,
|
||||
orig = orig,
|
||||
})
|
||||
end
|
||||
if y ~= " " then
|
||||
table.insert(groups.Unstaged, {
|
||||
section = "Unstaged",
|
||||
x = x,
|
||||
y = y,
|
||||
path = path,
|
||||
orig = orig,
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return branch, groups
|
||||
end
|
||||
|
||||
return M
|
||||
|
||||
Reference in New Issue
Block a user