Feat: Adds Ability to Merge MR (#147)

This adds the ability to merge an MR from within `gitlab.nvim` directly. If the reviewer is open, it'll be closed automatically. Users may configure whether they'd like to squash commits on the merge, as well as whether they'd like to delete the original source branch on a merge.

If squashing, users are prompted to provide an optional custom squash message for the squash commit.
This commit is contained in:
Harrison (Harry) Cramer
2023-12-17 14:28:21 -05:00
committed by GitHub
parent e254100a72
commit 64b36ac51d
12 changed files with 232 additions and 2 deletions

View File

@@ -0,0 +1,55 @@
local u = require("gitlab.utils")
local Popup = require("nui.popup")
local state = require("gitlab.state")
local job = require("gitlab.job")
local reviewer = require("gitlab.reviewer")
local M = {}
local function create_squash_message_popup()
return Popup(u.create_popup_state("Squash Commit Message", state.settings.popup.squash_message))
end
---@class MergeOpts
---@field delete_branch boolean?
---@field squash boolean?
---@field squash_message string?
---@param opts MergeOpts
M.merge = function(opts)
local merge_body = { squash = state.settings.merge.squash, delete_branch = state.settings.merge.delete_branch }
if opts then
merge_body.squash = opts.squash ~= nil and opts.squash
merge_body.delete_branch = opts.delete_branch ~= nil and opts.delete_branch
end
if state.INFO.detailed_merge_status ~= "mergeable" then
u.notify(string.format("MR not mergeable, currently '%s'", state.INFO.detailed_merge_status), vim.log.levels.ERROR)
return
end
if merge_body.squash then
local squash_message_popup = create_squash_message_popup()
squash_message_popup:mount()
state.set_popup_keymaps(squash_message_popup, function(text)
M.confirm_merge(merge_body, text)
end)
else
M.confirm_merge(merge_body)
end
end
---@param merge_body MergeOpts
---@param squash_message string?
M.confirm_merge = function(merge_body, squash_message)
if squash_message ~= nil then
merge_body.squash_message = squash_message
end
job.run_job("/merge", "POST", merge_body, function(data)
reviewer.close()
u.notify(data.message, vim.log.levels.INFO)
end)
end
return M

View File

@@ -122,7 +122,7 @@ M.build_info_lines = function()
author = { title = "Author", content = "@" .. info.author.username .. " (" .. info.author.name .. ")" },
created_at = { title = "Created", content = u.format_to_local(info.created_at, vim.fn.strftime("%z")) },
updated_at = { title = "Updated", content = u.format_to_local(info.updated_at, vim.fn.strftime("%z")) },
merge_status = { title = "Status", content = info.detailed_merge_status },
detailed_merge_status = { title = "Status", content = info.detailed_merge_status },
draft = { title = "Draft", content = (info.draft and "Yes" or "No") },
conflicts = { title = "Merge Conflicts", content = (info.has_conflicts and "Yes" or "No") },
assignees = { title = "Assignees", content = u.make_readable_list(info.assignees, "name") },
@@ -138,6 +138,9 @@ M.build_info_lines = function()
local longest_used = ""
for _, v in ipairs(state.settings.info.fields) do
if v == "merge_status" then
v = "detailed_merge_status"
end -- merge_status was deprecated, see https://gitlab.com/gitlab-org/gitlab/-/issues/3169#note_1162532204
local title = options[v].title
if string.len(title) > string.len(longest_used) then
longest_used = title
@@ -151,6 +154,9 @@ M.build_info_lines = function()
local lines = {}
for _, v in ipairs(state.settings.info.fields) do
if v == "merge_status" then
v = "detailed_merge_status"
end
local row = options[v]
local line = "* " .. row.title .. row_offset(row.title)
if type(row.content) == "function" then