local notify = require("snacks.notifier").notify local helpers = require("eta.helpers") local M = {} ---@class eta.gitlab.Session: eta.Session ---@field auth string personal access token `PRIVATE_TOKEN: ` ---@class eta.gitlab.Namespace ---@field full_path string ---@class eta.gitlab.Project ---@field id number ---@field name string ---@field path_with_namespace string ---@field tag_list string[] ---@field text? string ---@field namespace eta.gitlab.Namespace ---@field preview? {ft: string, text: string} ---@class eta.gitlab.Milestone ---@field id number ---@field title string ---@class eta.gitlab.Assignee ---@field username string ---@field id number ---@class eta.gitlab.Issue ---@field id number ---@field milestone eta.gitlab.Milestone ---@field title string ---@field assignees eta.gitlab.Assignee[] ---@field description string ---@field labels string[] ---@param session eta.gitlab.Session ---@return eta.gitlab.Project[] M.possible_projects = function(session) return helpers.request("get", session, "/projects", {simple="true", per_page="100"}) or {} end ---@param prj eta.gitlab.Project M._project_format = function(prj) local ret = {} ret[#ret + 1] = { prj.namespace.full_path .. "/", "SnacksPickerComment" } ret[#ret + 1] = { prj.name } return ret end ---@param self eta.gitlab.Session ---@return eta.gitlab.Project | nil M.update_current_project = function(self) local cmd = "git remote -v | grep fetch | cut -f2 | cut -d' ' -f1 | cut -d':' -f2" local handle, _ = io.popen(cmd, 'r') if not handle then return nil end local repo = handle:read("*a") handle:close() local prjs = M.possible_projects(self) for _, prj in ipairs(prjs) do if prj.path_with_namespace == repo then M.active_project = prj notify("selected " .. prj.path_with_namespace, "info", { title = "ETA", style = 'fancy' }) return prj end end end ---@type eta.gitlab.Project M.active_project = nil ---@param picker snacks.Picker ---@param item eta.gitlab.Project M._on_project_select = function(picker, item) M.active_project = item picker:close() notify("selected " .. item.path_with_namespace, "info", { title = "ETA", style = 'fancy' }) end ---@param self eta.gitlab.Session M.select_project = function(self) local prjs = M.possible_projects(self) require("snacks.picker").pick({ title = "Select Project", format = M._project_format, preview = "preview", confirm = M._on_project_select, items = prjs }) end ---@param self eta.gitlab.Session ---@return eta.gitlab.Issue[] M.active_issues = function(self) if not M.active_project then if not M.update_current_project(self) then M.select_project(self) end end return request("get", self, "/projects/" .. tostring(M.active_project.id) .. "/issues", {}) end ---@param self eta.gitlab.Session ---@param name string ---@param clickup_task_id string ---@param tags string[] M.new_issue = function(self, name, clickup_task_id, tags) if not M.active_project then if not M.update_current_project(self) then M.select_project(self) end end local description = "%23" .. clickup_task_id local title = name:gsub("%s", "%20") return request("post", self, "/projects/" .. tostring(M.active_project.id) .. "/issues", { title=title, description=description, labels=table.concat(tags, ",") }) end ---@param self eta.gitlab.Session ---@param name string ---@param issue number ---@param clickup_task_id string ---@param tags string[] M.new_mr = function(self, name, issue, clickup_task_id, tags) if not M.active_project then if not M.update_current_project(self) then M.select_project(self) end end local description = "Closes %23" .. tostring(issue) .. " | %23" .. clickup_task_id local title = name:gsub("%s", "%20") return request("post", self, "/projects/" .. tostring(M.active_project.id) .. "/merge_requests", { title=title, description=description, labels=table.concat(tags, ",") }) end return M