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