feat: first implementation for issues and pull requests
This commit is contained in:
@@ -1,196 +1,64 @@
|
||||
local config = require("gitea.config")
|
||||
local auth = require("gitea.auth")
|
||||
local curl = require("plenary.curl")
|
||||
local Job = require('plenary.job')
|
||||
local api = {}
|
||||
|
||||
local M = {}
|
||||
-- Helper function for making async requests to Gitea API via curl
|
||||
local function request(method, base_url, endpoint, token, data, callback)
|
||||
local headers = {
|
||||
"Content-Type: application/json",
|
||||
"Authorization: token " .. token
|
||||
}
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- Helper: get base URL from config
|
||||
------------------------------------------------------------------------------
|
||||
local function get_base_url()
|
||||
return config.values.server_url
|
||||
end
|
||||
local curl_args = {
|
||||
"-s", -- silent mode
|
||||
"-X", method, -- GET, POST, PATCH, etc.
|
||||
base_url .. endpoint,
|
||||
"-H", headers[1],
|
||||
"-H", headers[2]
|
||||
}
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- Helper: get auth header by trimming token
|
||||
------------------------------------------------------------------------------
|
||||
local function get_auth_header()
|
||||
local token = auth.get_token()
|
||||
if not token or token == "" then
|
||||
error("[gitea.nvim] Missing Gitea token.")
|
||||
end
|
||||
return "token " .. token
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- Main HTTP request helper (using plenary.curl)
|
||||
------------------------------------------------------------------------------
|
||||
local function request(method, endpoint, opts)
|
||||
opts = opts or {}
|
||||
local url = get_base_url() .. endpoint
|
||||
local headers = opts.headers or {}
|
||||
headers["Authorization"] = get_auth_header()
|
||||
headers["Content-Type"] = "application/json"
|
||||
|
||||
local body_data
|
||||
if opts.body then
|
||||
body_data = vim.json.encode(opts.body)
|
||||
if data then
|
||||
local json_data = vim.fn.json_encode(data)
|
||||
table.insert(curl_args, "-d")
|
||||
table.insert(curl_args, json_data)
|
||||
end
|
||||
|
||||
local result = curl.request({
|
||||
url = url,
|
||||
method = method,
|
||||
headers = headers,
|
||||
timeout = 10000,
|
||||
body = body_data,
|
||||
query = opts.query,
|
||||
})
|
||||
|
||||
return result
|
||||
Job:new({
|
||||
command = "curl",
|
||||
args = curl_args,
|
||||
on_exit = function(j, return_val)
|
||||
if return_val == 0 then
|
||||
local result = table.concat(j:result(), "\n")
|
||||
local ok, decoded = pcall(vim.fn.json_decode, result)
|
||||
if ok then
|
||||
callback(decoded, nil)
|
||||
else
|
||||
callback(nil, "Failed to decode JSON. Response: " .. result)
|
||||
end
|
||||
else
|
||||
callback(nil, "Curl request failed with return code: " .. return_val)
|
||||
end
|
||||
end
|
||||
}):start()
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- Issues
|
||||
------------------------------------------------------------------------------
|
||||
function M.list_issues(owner, repo, opts)
|
||||
local endpoint = string.format("/api/v1/repos/%s/%s/issues", owner, repo)
|
||||
local result = request("GET", endpoint, { query = opts })
|
||||
if result and result.status == 200 then
|
||||
return vim.json.decode(result.body)
|
||||
end
|
||||
return nil, result and result.status
|
||||
function api.get(base_url, endpoint, token, cb)
|
||||
request("GET", base_url, endpoint, token, nil, cb)
|
||||
end
|
||||
|
||||
function M.get_issue(owner, repo, number)
|
||||
local endpoint = string.format("/api/v1/repos/%s/%s/issues/%d", owner, repo, number)
|
||||
local result = request("GET", endpoint)
|
||||
if result and result.status == 200 then
|
||||
return vim.json.decode(result.body)
|
||||
end
|
||||
return nil, result and result.status
|
||||
function api.post(base_url, endpoint, token, data, cb)
|
||||
request("POST", base_url, endpoint, token, data, cb)
|
||||
end
|
||||
|
||||
function M.create_issue(owner, repo, data)
|
||||
local endpoint = string.format("/api/v1/repos/%s/%s/issues", owner, repo)
|
||||
local result = request("POST", endpoint, { body = data })
|
||||
if result and result.status == 201 then
|
||||
return vim.json.decode(result.body)
|
||||
end
|
||||
return nil, result and result.status
|
||||
function api.patch(base_url, endpoint, token, data, cb)
|
||||
request("PATCH", base_url, endpoint, token, data, cb)
|
||||
end
|
||||
|
||||
-- CHANGED: treat both 200 and 201 as success, in case Gitea returns 201
|
||||
function M.edit_issue(owner, repo, number, data)
|
||||
local endpoint = string.format("/api/v1/repos/%s/%s/issues/%d", owner, repo, number)
|
||||
local result = request("PATCH", endpoint, { body = data })
|
||||
if result and (result.status == 200 or result.status == 201) then
|
||||
return vim.json.decode(result.body)
|
||||
end
|
||||
return nil, result and result.status
|
||||
function api.put(base_url, endpoint, token, data, cb)
|
||||
request("PUT", base_url, endpoint, token, data, cb)
|
||||
end
|
||||
|
||||
function M.close_issue(owner, repo, number)
|
||||
return M.edit_issue(owner, repo, number, { state = "closed" })
|
||||
function api.delete(base_url, endpoint, token, cb)
|
||||
request("DELETE", base_url, endpoint, token, nil, cb)
|
||||
end
|
||||
|
||||
function M.reopen_issue(owner, repo, number)
|
||||
return M.edit_issue(owner, repo, number, { state = "open" })
|
||||
end
|
||||
|
||||
function M.comment_issue(owner, repo, number, body)
|
||||
local endpoint = string.format("/api/v1/repos/%s/%s/issues/%d/comments", owner, repo, number)
|
||||
local result = request("POST", endpoint, { body = { body = body } })
|
||||
if result and result.status == 201 then
|
||||
return vim.json.decode(result.body)
|
||||
end
|
||||
return nil, result and result.status
|
||||
end
|
||||
|
||||
-- CHANGED: treat both 200 and 201 as success
|
||||
function M.edit_issue_comment(owner, repo, number, comment_id, body)
|
||||
local endpoint = string.format("/api/v1/repos/%s/%s/issues/comments/%d", owner, repo, comment_id)
|
||||
local result = request("PATCH", endpoint, { body = { body = body } })
|
||||
if result and (result.status == 200 or result.status == 201) then
|
||||
return vim.json.decode(result.body)
|
||||
end
|
||||
return nil, result and result.status
|
||||
end
|
||||
|
||||
function M.get_issue_comments(owner, repo, number)
|
||||
local endpoint = string.format("/api/v1/repos/%s/%s/issues/%d/comments", owner, repo, number)
|
||||
local result = request("GET", endpoint)
|
||||
if result and result.status == 200 then
|
||||
return vim.json.decode(result.body)
|
||||
end
|
||||
return nil, result and result.status
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- Pull Requests
|
||||
------------------------------------------------------------------------------
|
||||
function M.list_pull_requests(owner, repo, opts)
|
||||
local endpoint = string.format("/api/v1/repos/%s/%s/pulls", owner, repo)
|
||||
local result = request("GET", endpoint, { query = opts })
|
||||
if result and result.status == 200 then
|
||||
return vim.json.decode(result.body)
|
||||
end
|
||||
return nil, result and result.status
|
||||
end
|
||||
|
||||
function M.get_pull_request(owner, repo, number)
|
||||
local endpoint = string.format("/api/v1/repos/%s/%s/pulls/%d", owner, repo, number)
|
||||
local result = request("GET", endpoint)
|
||||
if result and result.status == 200 then
|
||||
return vim.json.decode(result.body)
|
||||
end
|
||||
return nil, result and result.status
|
||||
end
|
||||
|
||||
function M.create_pull_request(owner, repo, data)
|
||||
local endpoint = string.format("/api/v1/repos/%s/%s/pulls", owner, repo)
|
||||
local result = request("POST", endpoint, { body = data })
|
||||
if result and result.status == 201 then
|
||||
return vim.json.decode(result.body)
|
||||
end
|
||||
return nil, result and result.status
|
||||
end
|
||||
|
||||
-- CHANGED: treat both 200 and 201 as success for PR edits
|
||||
function M.edit_pull_request(owner, repo, number, data)
|
||||
local endpoint = string.format("/api/v1/repos/%s/%s/pulls/%d", owner, repo, number)
|
||||
local result = request("PATCH", endpoint, { body = data })
|
||||
if result and (result.status == 200 or result.status == 201) then
|
||||
return vim.json.decode(result.body)
|
||||
end
|
||||
return nil, result and result.status
|
||||
end
|
||||
|
||||
function M.merge_pull_request(owner, repo, number, merge_style, merge_title, merge_message)
|
||||
local endpoint = string.format("/api/v1/repos/%s/%s/pulls/%d/merge", owner, repo, number)
|
||||
local result = request("POST", endpoint, {
|
||||
body = {
|
||||
Do = merge_style or "merge",
|
||||
MergeTitleField = merge_title or "",
|
||||
MergeMessageField = merge_message or "",
|
||||
}
|
||||
})
|
||||
if result and result.status == 200 then
|
||||
return vim.json.decode(result.body)
|
||||
end
|
||||
return nil, result and result.status
|
||||
end
|
||||
|
||||
function M.close_pull_request(owner, repo, number)
|
||||
return M.edit_pull_request(owner, repo, number, { state = "closed" })
|
||||
end
|
||||
|
||||
function M.reopen_pull_request(owner, repo, number)
|
||||
return M.edit_pull_request(owner, repo, number, { state = "open" })
|
||||
end
|
||||
|
||||
function M.comment_pull_request(owner, repo, number, body)
|
||||
-- Uses same logic as comment_issue
|
||||
return M.comment_issue(owner, repo, number, body)
|
||||
end
|
||||
|
||||
return M
|
||||
return api
|
||||
|
||||
Reference in New Issue
Block a user