local forge = require('forge') ---@class forge.Codeberg: forge.Forge local M = { name = 'codeberg', cli = 'tea', kinds = { issue = 'issues', pr = 'pulls' }, labels = { issue = 'Issues', pr = 'PRs', pr_one = 'PR', pr_full = 'Pull Requests', ci = 'CI/CD', }, } ---@param state string ---@return string[] function M:list_pr_json_cmd(state) return { 'tea', 'pulls', 'list', '--state', state, '--output', 'json', '--fields', 'index,title,head,state,poster,created_at', } end ---@param state string ---@return string[] function M:list_issue_json_cmd(state) return { 'tea', 'issues', 'list', '--state', state, '--output', 'json', '--fields', 'index,title,state,poster,created_at', } end function M:pr_json_fields() return { number = 'index', title = 'title', branch = 'head', state = 'state', author = 'poster', created_at = 'created_at', } end function M:issue_json_fields() return { number = 'index', title = 'title', state = 'state', author = 'poster', created_at = 'created_at', } end ---@param kind string ---@param num string function M:view_web(kind, num) local base = forge.remote_web_url() vim.ui.open(('%s/%s/%s'):format(base, kind, num)) end ---@param loc string ---@param branch string function M:browse(loc, branch) local base = forge.remote_web_url() local file, lines = loc:match('^(.+):(.+)$') vim.ui.open(('%s/src/branch/%s/%s#L%s'):format(base, branch, file, lines)) end function M:browse_root() vim.ui.open(forge.remote_web_url()) end function M:browse_branch(branch) local base = forge.remote_web_url() vim.ui.open(base .. '/src/branch/' .. branch) end function M:browse_commit(sha) local base = forge.remote_web_url() vim.ui.open(base .. '/commit/' .. sha) end function M:checkout_cmd(num) return { 'tea', 'pr', 'checkout', num } end ---@param loc string function M:yank_branch(loc) local branch = vim.trim(vim.fn.system('git branch --show-current')) local base = forge.remote_web_url() local file, lines = loc:match('^(.+):(.+)$') vim.fn.setreg('+', ('%s/src/branch/%s/%s#L%s'):format(base, branch, file, lines)) end ---@param loc string function M:yank_commit(loc) local commit = vim.trim(vim.fn.system('git rev-parse HEAD')) local base = forge.remote_web_url() local file, lines = loc:match('^(.+):(.+)$') vim.fn.setreg('+', ('%s/src/commit/%s/%s#L%s'):format(base, commit, file, lines)) end ---@param num string ---@return string[] function M:fetch_pr(num) return { 'git', 'fetch', 'origin', ('pull/%s/head:pr-%s'):format(num, num) } end ---@param num string ---@return string[] function M:pr_base_cmd(num) return { 'tea', 'pr', num, '--fields', 'base', '--output', 'simple' } end ---@param _branch string ---@return string[] function M:pr_for_branch_cmd(_branch) return { 'tea', 'pr', 'list', '--fields', 'index,head', '--output', 'simple', '--state', 'open', } end ---@param num string ---@return string function M:checks_cmd(num) local _ = num return 'tea actions runs list' end ---@param run_id string ---@param failed_only boolean ---@return string[] function M:check_log_cmd(run_id, failed_only) local _ = failed_only local lines = forge.config().ci.lines return { 'sh', '-c', ('tea actions runs logs %s | tail -n %d'):format(run_id, lines), } end ---@param run_id string ---@return string[] function M:check_tail_cmd(run_id) return { 'tea', 'actions', 'runs', 'logs', run_id, '--follow' } end function M:list_runs_cmd(_branch) return 'tea actions runs list' end function M:run_log_cmd(id, failed_only) local _ = failed_only local lines = forge.config().ci.lines return { 'sh', '-c', ('tea actions runs logs %s | tail -n %d'):format(id, lines), } end function M:run_tail_cmd(id) return { 'tea', 'actions', 'runs', 'logs', id, '--follow' } end ---@param num string ---@param method string ---@return string[] function M:merge_cmd(num, method) return { 'tea', 'pr', 'merge', num, '--style', method } end ---@param num string ---@return string[] function M:approve_cmd(num) return { 'tea', 'pr', 'approve', num } end ---@param num string ---@return string[] function M:close_cmd(num) return { 'tea', 'pulls', 'close', num } end ---@param num string ---@return string[] function M:reopen_cmd(num) return { 'tea', 'pulls', 'reopen', num } end ---@param num string ---@return string[] function M:close_issue_cmd(num) return { 'tea', 'issues', 'close', num } end ---@param num string ---@return string[] function M:reopen_issue_cmd(num) return { 'tea', 'issues', 'reopen', num } end ---@param title string ---@param body string ---@param base string ---@param _draft boolean ---@param _reviewers string[]? ---@return string[] function M:create_pr_cmd(title, body, base, _draft, _reviewers) return { 'tea', 'pr', 'create', '--title', title, '--description', body, '--base', base } end ---@return string[]? function M:create_pr_web_cmd() local branch = vim.trim(vim.fn.system('git branch --show-current')) local base_url = forge.remote_web_url() local default = vim.trim( vim.fn.system( "git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's|refs/remotes/origin/||'" ) ) if default == '' then default = 'main' end vim.ui.open(('%s/compare/%s...%s'):format(base_url, default, branch)) return nil end ---@return string[] function M:default_branch_cmd() return { 'sh', '-c', "git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's|refs/remotes/origin/||'", } end ---@return string[] function M:template_paths() return { '.gitea/pull_request_template.md', '.github/pull_request_template.md', '.github/PULL_REQUEST_TEMPLATE.md', } end ---@param _num string ---@param _is_draft boolean ---@return string[]? function M:draft_toggle_cmd(_num, _is_draft) return nil end ---@return forge.RepoInfo function M:repo_info() return { permission = 'ADMIN', merge_methods = { 'squash', 'rebase', 'merge' }, } end ---@param num string ---@return forge.PRState function M:pr_state(num) local result = vim .system({ 'tea', 'pr', num, '--fields', 'state,mergeable', '--output', 'json' }, { text = true }) :wait() local ok, data = pcall(vim.json.decode, result.stdout or '{}') if not ok or type(data) ~= 'table' then data = {} end return { state = (data.state or 'unknown'):upper(), mergeable = data.mergeable and 'MERGEABLE' or 'UNKNOWN', review_decision = '', is_draft = false, } end return M