161 lines
4.7 KiB
Lua
161 lines
4.7 KiB
Lua
local config = require("gitea.config")
|
|
local uv = vim.loop
|
|
|
|
local M = {}
|
|
local token_cached = nil
|
|
|
|
-- Attempt to read the token file from disk
|
|
local function read_token_file(path)
|
|
local fd = uv.fs_open(path, "r", 438) -- 0666 in decimal
|
|
if not fd then return nil end
|
|
local stat = uv.fs_fstat(fd)
|
|
local data = uv.fs_read(fd, stat.size, 0)
|
|
uv.fs_close(fd)
|
|
return data
|
|
end
|
|
|
|
-- Write token file
|
|
local function write_token_file(path, token)
|
|
local fd = uv.fs_open(path, "w", 384) -- 0600 in decimal
|
|
if not fd then
|
|
error("[gitea.nvim] Failed to open token file for writing: " .. path)
|
|
end
|
|
uv.fs_write(fd, token, -1)
|
|
uv.fs_close(fd)
|
|
end
|
|
|
|
-- Checks if the token file is in .gitignore, if not ask user
|
|
local function ensure_ignored(token_file, ignore_file)
|
|
-- Read .gitignore lines if present
|
|
local file = io.open(ignore_file, "r")
|
|
local lines = {}
|
|
if file then
|
|
for line in file:lines() do
|
|
table.insert(lines, line)
|
|
end
|
|
file:close()
|
|
end
|
|
-- Check if token_file is in .gitignore
|
|
for _, l in ipairs(lines) do
|
|
if l == token_file then
|
|
return
|
|
end
|
|
end
|
|
-- Not in ignore, ask user
|
|
vim.schedule(function()
|
|
vim.cmd([[echohl WarningMsg]])
|
|
vim.cmd([[echo "gitea.nvim: We recommend adding ']]..token_file..[[' to ']]..ignore_file..[['. Add now? (y/N)"]])
|
|
vim.cmd([[echohl None]])
|
|
|
|
local ans = vim.fn.getchar()
|
|
ans = vim.fn.nr2char(ans)
|
|
|
|
if ans == "y" or ans == "Y" then
|
|
local f = io.open(ignore_file, "a")
|
|
if f then
|
|
f:write("\n" .. token_file .. "\n")
|
|
f:close()
|
|
vim.notify("Added '"..token_file.."' to '"..ignore_file.."'", vim.log.levels.INFO)
|
|
else
|
|
vim.notify("Failed to open '"..ignore_file.."' for appending.", vim.log.levels.ERROR)
|
|
end
|
|
else
|
|
vim.notify("Ok, not adding token file to '"..ignore_file.."'. Be mindful of security!", vim.log.levels.WARN)
|
|
end
|
|
end)
|
|
end
|
|
|
|
-- Parse .git/config or `git remote get-url origin` to guess the Gitea server
|
|
local function detect_gitea_server()
|
|
-- Attempt: use `git config remote.origin.url`
|
|
local cmd = "git config remote.origin.url"
|
|
local url = vim.fn.systemlist(cmd)[1]
|
|
if vim.v.shell_error ~= 0 or not url or url == "" then
|
|
return nil
|
|
end
|
|
-- Example: https://gitea.myserver.com/owner/repo.git
|
|
-- Strip `.git` suffix if present
|
|
url = url:gsub("%.git$", "")
|
|
-- Attempt to extract domain, e.g. "https://gitea.myserver.com"
|
|
-- We'll do a naive pattern match
|
|
local protocol, domain_and_path = url:match("^(https?://)(.*)$")
|
|
if not protocol or not domain_and_path then
|
|
-- Could be SSH or something else
|
|
-- For instance: git@gitea.myserver.com:owner/repo.git
|
|
-- Try a different parse
|
|
local user_host, path = url:match("^(.-):(.*)$")
|
|
if user_host and path and user_host:match(".*@") then
|
|
-- user_host could be "git@gitea.myserver.com"
|
|
local host = user_host:match("@(.*)")
|
|
if host then
|
|
return "https://"..host
|
|
end
|
|
end
|
|
-- Fallback
|
|
return nil
|
|
end
|
|
|
|
-- domain_and_path might be "gitea.myserver.com/owner/repo"
|
|
-- just extract "gitea.myserver.com"
|
|
local server = domain_and_path:match("^([^/]+)")
|
|
if not server then
|
|
return nil
|
|
end
|
|
return protocol .. server
|
|
end
|
|
|
|
-- Called during plugin setup or first command usage
|
|
function M.ensure_token()
|
|
if token_cached then
|
|
return token_cached
|
|
end
|
|
|
|
local cfg = config.values
|
|
local token_file = cfg.config_file
|
|
local ignore_file = cfg.ignore_file
|
|
|
|
-- Attempt to detect the Gitea server if not provided
|
|
if not cfg.server_url or cfg.server_url == "" then
|
|
cfg.server_url = detect_gitea_server()
|
|
end
|
|
if not cfg.server_url then
|
|
vim.notify("[gitea.nvim] Could not detect Gitea server from .git/config. Please configure manually.", vim.log.levels.WARN)
|
|
end
|
|
|
|
local token_data = read_token_file(token_file)
|
|
if token_data and token_data ~= "" then
|
|
token_cached = token_data
|
|
return token_cached
|
|
end
|
|
|
|
-- If we reach here, no token was found
|
|
vim.schedule(function()
|
|
vim.cmd([[echohl WarningMsg]])
|
|
vim.cmd([[echo "gitea.nvim: No Gitea token found. Please enter your Gitea Personal Access Token:"]])
|
|
vim.cmd([[echohl None]])
|
|
|
|
local user_token = vim.fn.input("Token: ")
|
|
vim.cmd("redraw")
|
|
|
|
if user_token == nil or user_token == "" then
|
|
vim.notify("[gitea.nvim] No token provided, plugin may not work properly.", vim.log.levels.ERROR)
|
|
return
|
|
end
|
|
|
|
write_token_file(token_file, user_token)
|
|
token_cached = user_token
|
|
vim.notify("Token saved to " .. token_file .. ".", vim.log.levels.INFO)
|
|
|
|
-- Offer to add token_file to .gitignore
|
|
ensure_ignored(token_file, ignore_file)
|
|
end)
|
|
|
|
return nil
|
|
end
|
|
|
|
function M.get_token()
|
|
return token_cached
|
|
end
|
|
|
|
return M
|