Release: Bug Fixes and Improvements (#399)
fix: Error messages and run all tests (#381) feat: Automatically open fold under cursor (#380) fix: Discussion ID is not required (#383) chore: Add more emojis (#384) fix: Publish all drafts (#391) fix: Make discussion tree buffers no-modifiable (#394) fix: Incorrect warning about commits (#395) fix: Show draft replies in the correct tree (#396) fix: Cannot choose merge requests (#398) --------- Co-authored-by: George Kontridze <george.kontridze@gmail.com> Co-authored-by: Jakub F. Bortlík <jakub.bortlik@proton.me>
This commit is contained in:
committed by
GitHub
parent
38bde8a0e4
commit
341d56a1cb
@@ -11,7 +11,7 @@ type PluginOptions struct {
|
|||||||
GitlabRequest bool `json:"gitlab_request"`
|
GitlabRequest bool `json:"gitlab_request"`
|
||||||
GitlabResponse bool `json:"gitlab_response"`
|
GitlabResponse bool `json:"gitlab_response"`
|
||||||
} `json:"debug"`
|
} `json:"debug"`
|
||||||
ChosenTargetBranch *string `json:"chosen_target_branch,omitempty"`
|
ChosenMrIID int `json:"chosen_mr_iid"`
|
||||||
ConnectionSettings struct {
|
ConnectionSettings struct {
|
||||||
Insecure bool `json:"insecure"`
|
Insecure bool `json:"insecure"`
|
||||||
Remote string `json:"remote"`
|
Remote string `json:"remote"`
|
||||||
|
|||||||
@@ -105,7 +105,10 @@ func (m withMrMiddleware) handle(next http.Handler) http.Handler {
|
|||||||
options := gitlab.ListProjectMergeRequestsOptions{
|
options := gitlab.ListProjectMergeRequestsOptions{
|
||||||
Scope: gitlab.Ptr("all"),
|
Scope: gitlab.Ptr("all"),
|
||||||
SourceBranch: &m.data.gitInfo.BranchName,
|
SourceBranch: &m.data.gitInfo.BranchName,
|
||||||
TargetBranch: pluginOptions.ChosenTargetBranch,
|
}
|
||||||
|
|
||||||
|
if pluginOptions.ChosenMrIID != 0 {
|
||||||
|
options.IIDs = gitlab.Ptr([]int{pluginOptions.ChosenMrIID})
|
||||||
}
|
}
|
||||||
|
|
||||||
mergeRequests, _, err := m.client.ListProjectMergeRequests(m.data.projectInfo.ProjectId, &options)
|
mergeRequests, _, err := m.client.ListProjectMergeRequests(m.data.projectInfo.ProjectId, &options)
|
||||||
|
|||||||
@@ -6351,6 +6351,38 @@
|
|||||||
],
|
],
|
||||||
"moji": "😮"
|
"moji": "😮"
|
||||||
},
|
},
|
||||||
|
"package": {
|
||||||
|
"unicode": "1F4E6",
|
||||||
|
"unicode_alternates": [],
|
||||||
|
"name": "package",
|
||||||
|
"shortname": ":package:",
|
||||||
|
"category": "people",
|
||||||
|
"aliases": [],
|
||||||
|
"aliases_ascii": [],
|
||||||
|
"keywords": [
|
||||||
|
"release"
|
||||||
|
],
|
||||||
|
"moji": "📦"
|
||||||
|
},
|
||||||
|
"party": {
|
||||||
|
"unicode": "1F389",
|
||||||
|
"unicode_alternates": [],
|
||||||
|
"name": "party popper as a 'tada' celebration",
|
||||||
|
"shortname": ":tada:",
|
||||||
|
"category": "people",
|
||||||
|
"aliases": [
|
||||||
|
":party_popper:"
|
||||||
|
],
|
||||||
|
"aliases_ascii": [],
|
||||||
|
"keywords": [
|
||||||
|
"celebrate",
|
||||||
|
"celebration",
|
||||||
|
"hooray",
|
||||||
|
"hurrah",
|
||||||
|
"hurray"
|
||||||
|
],
|
||||||
|
"moji": "🎉"
|
||||||
|
},
|
||||||
"pensive": {
|
"pensive": {
|
||||||
"unicode": "1F614",
|
"unicode": "1F614",
|
||||||
"unicode_alternates": [],
|
"unicode_alternates": [],
|
||||||
@@ -8445,6 +8477,19 @@
|
|||||||
],
|
],
|
||||||
"moji": "🤖"
|
"moji": "🤖"
|
||||||
},
|
},
|
||||||
|
"rocket": {
|
||||||
|
"unicode": "1F680",
|
||||||
|
"unicode_alternates": [],
|
||||||
|
"name": "rocket",
|
||||||
|
"shortname": ":rocket:",
|
||||||
|
"category": "people",
|
||||||
|
"aliases": [],
|
||||||
|
"aliases_ascii": [],
|
||||||
|
"keywords": [
|
||||||
|
"space"
|
||||||
|
],
|
||||||
|
"moji": "🚀"
|
||||||
|
},
|
||||||
"rofl": {
|
"rofl": {
|
||||||
"unicode": "1F923",
|
"unicode": "1F923",
|
||||||
"unicode_alternates": [],
|
"unicode_alternates": [],
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ M.add_empty_titles = function()
|
|||||||
{ end_row = linnr - 1, end_col = string.len(v.title), hl_group = "TitleHighlight" }
|
{ end_row = linnr - 1, end_col = string.len(v.title), hl_group = "TitleHighlight" }
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
M.switch_can_edit_bufs(false, v.bufnr)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ end
|
|||||||
--- continue working on it.
|
--- continue working on it.
|
||||||
---@param args? Mr
|
---@param args? Mr
|
||||||
M.start = function(args)
|
M.start = function(args)
|
||||||
if not git.current_branch_up_to_date_on_remote(vim.log.levels.ERROR) then
|
if not git.check_current_branch_up_to_date_on_remote(vim.log.levels.ERROR) then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -49,9 +49,16 @@ local function content()
|
|||||||
local resolvable_notes, resolved_notes = get_data(state.DISCUSSION_DATA.unlinked_discussions)
|
local resolvable_notes, resolved_notes = get_data(state.DISCUSSION_DATA.unlinked_discussions)
|
||||||
|
|
||||||
local draft_notes = require("gitlab.actions.draft_notes")
|
local draft_notes = require("gitlab.actions.draft_notes")
|
||||||
local inline_draft_notes = List.new(state.DRAFT_NOTES):filter(draft_notes.has_position)
|
local inline_draft_notes, unlinked_draft_notes = List.new(state.DRAFT_NOTES):partition(function(note)
|
||||||
local unlinked_draft_notes = List.new(state.DRAFT_NOTES):filter(function(note)
|
if note.discussion_id == "" then
|
||||||
return not draft_notes.has_position(note)
|
return draft_notes.has_position(note)
|
||||||
|
end
|
||||||
|
for _, discussion in ipairs(state.DISCUSSION_DATA.unlinked_discussions) do
|
||||||
|
if discussion.id == note.discussion_id then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
end)
|
end)
|
||||||
|
|
||||||
local t = {
|
local t = {
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ end
|
|||||||
|
|
||||||
---Publishes all draft notes and comments. Re-renders all discussion views.
|
---Publishes all draft notes and comments. Re-renders all discussion views.
|
||||||
M.confirm_publish_all_drafts = function()
|
M.confirm_publish_all_drafts = function()
|
||||||
local body = {}
|
local body = { publish_all = true }
|
||||||
job.run_job("/mr/draft_notes/publish", "POST", body, function(data)
|
job.run_job("/mr/draft_notes/publish", "POST", body, function(data)
|
||||||
u.notify(data.message, vim.log.levels.INFO)
|
u.notify(data.message, vim.log.levels.INFO)
|
||||||
state.DRAFT_NOTES = {}
|
state.DRAFT_NOTES = {}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ M.choose_merge_request = function(opts)
|
|||||||
end
|
end
|
||||||
|
|
||||||
vim.schedule(function()
|
vim.schedule(function()
|
||||||
state.chosen_target_branch = choice.target_branch
|
state.chosen_mr_iid = choice.iid
|
||||||
require("gitlab.server").restart(function()
|
require("gitlab.server").restart(function()
|
||||||
if opts.open_reviewer then
|
if opts.open_reviewer then
|
||||||
require("gitlab").review()
|
require("gitlab").review()
|
||||||
|
|||||||
@@ -82,7 +82,8 @@ M.summary = function()
|
|||||||
vim.api.nvim_set_current_buf(description_popup.bufnr)
|
vim.api.nvim_set_current_buf(description_popup.bufnr)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
git.current_branch_up_to_date_on_remote(vim.log.levels.WARN)
|
git.check_current_branch_up_to_date_on_remote(vim.log.levels.WARN)
|
||||||
|
git.check_mr_in_good_condition()
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Builds a lua list of strings that contain metadata about the current MR. Only builds the
|
-- Builds a lua list of strings that contain metadata about the current MR. Only builds the
|
||||||
|
|||||||
@@ -43,6 +43,58 @@ M.switch_branch = function(branch)
|
|||||||
return run_system({ "git", "checkout", "-q", branch })
|
return run_system({ "git", "checkout", "-q", branch })
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---Fetches the name of the remote tracking branch for the current branch
|
||||||
|
---@return string|nil, string|nil
|
||||||
|
M.get_remote_branch = function()
|
||||||
|
return run_system({ "git", "rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{u}" })
|
||||||
|
end
|
||||||
|
|
||||||
|
---Determines whether the tracking branch is ahead of or behind the current branch, and warns the user if so
|
||||||
|
---@param current_branch string
|
||||||
|
---@param remote_branch string
|
||||||
|
---@param log_level number
|
||||||
|
---@return boolean
|
||||||
|
M.get_ahead_behind = function(current_branch, remote_branch, log_level)
|
||||||
|
local u = require("gitlab.utils")
|
||||||
|
local result, err =
|
||||||
|
run_system({ "git", "rev-list", "--left-right", "--count", current_branch .. "..." .. remote_branch })
|
||||||
|
if err ~= nil or result == nil then
|
||||||
|
u.notify("Could not determine if branch is up-to-date: " .. err, vim.log.levels.ERROR)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
local ahead, behind = result:match("(%d+)%s+(%d+)")
|
||||||
|
if ahead == nil or behind == nil then
|
||||||
|
u.notify("Error parsing ahead/behind information.", vim.log.levels.ERROR)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
ahead = tonumber(ahead)
|
||||||
|
behind = tonumber(behind)
|
||||||
|
|
||||||
|
if ahead > 0 and behind == 0 then
|
||||||
|
u.notify(string.format("There are local changes that haven't been pushed to %s yet", remote_branch), log_level)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
if behind > 0 and ahead == 0 then
|
||||||
|
u.notify(string.format("There are remote changes on %s that haven't been pulled yet", remote_branch), log_level)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
if ahead > 0 and behind > 0 then
|
||||||
|
u.notify(
|
||||||
|
string.format(
|
||||||
|
"Your branch and the remote %s have diverged. You need to pull, possibly rebase, and then push.",
|
||||||
|
remote_branch
|
||||||
|
),
|
||||||
|
log_level
|
||||||
|
)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
return true -- Checks passed, branch is up-to-date
|
||||||
|
end
|
||||||
|
|
||||||
---Return the name of the current branch
|
---Return the name of the current branch
|
||||||
---@return string|nil, string|nil
|
---@return string|nil, string|nil
|
||||||
M.get_current_branch = function()
|
M.get_current_branch = function()
|
||||||
@@ -93,39 +145,45 @@ M.contains_branch = function(current_branch)
|
|||||||
return run_system({ "git", "branch", "-r", "--contains", current_branch })
|
return run_system({ "git", "branch", "-r", "--contains", current_branch })
|
||||||
end
|
end
|
||||||
|
|
||||||
---Returns true if `branch` is up-to-date on remote, false otherwise.
|
---Returns true if `branch` is up-to-date on remote, otherwise false and warns user
|
||||||
---@param log_level integer
|
---@param log_level integer
|
||||||
---@return boolean|nil
|
---@return boolean
|
||||||
M.current_branch_up_to_date_on_remote = function(log_level)
|
M.check_current_branch_up_to_date_on_remote = function(log_level)
|
||||||
|
local u = require("gitlab.utils")
|
||||||
|
|
||||||
|
-- Get current branch
|
||||||
|
local current_branch, err_current_branch = M.get_current_branch()
|
||||||
|
if err_current_branch or not current_branch then
|
||||||
|
u.notify("Could not get current branch: " .. err_current_branch, vim.log.levels.ERROR)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Get remote tracking branch
|
||||||
|
local remote_branch, err_remote_branch = M.get_remote_branch()
|
||||||
|
if err_remote_branch or not remote_branch then
|
||||||
|
u.notify("Could not get remote branch: " .. err_remote_branch, vim.log.levels.ERROR)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
return M.get_ahead_behind(current_branch, remote_branch, log_level)
|
||||||
|
end
|
||||||
|
|
||||||
|
---Warns user if the current MR is in a bad state (closed, has conflicts, merged)
|
||||||
|
M.check_mr_in_good_condition = function()
|
||||||
local state = require("gitlab.state")
|
local state = require("gitlab.state")
|
||||||
local current_branch = M.get_current_branch()
|
local u = require("gitlab.utils")
|
||||||
local handle = io.popen("git branch -r --contains " .. current_branch .. " 2>&1")
|
|
||||||
if not handle then
|
if state.INFO.has_conflicts then
|
||||||
require("gitlab.utils").notify("Error running 'git branch' command.", vim.log.levels.ERROR)
|
u.notify("This merge request has conflicts!", vim.log.levels.WARN)
|
||||||
return nil
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local remote_branches_with_current_head = {}
|
if state.INFO.state == "closed" then
|
||||||
for line in handle:lines() do
|
u.notify(string.format("This MR was closed %s", u.time_since(state.INFO.closed_at)), vim.log.levels.WARN)
|
||||||
table.insert(remote_branches_with_current_head, line)
|
|
||||||
end
|
end
|
||||||
handle:close()
|
|
||||||
|
|
||||||
local current_head_on_remote = List.new(remote_branches_with_current_head):filter(function(line)
|
if state.INFO.state == "merged" then
|
||||||
return line == string.format(" %s/", state.settings.connection_settings.remote) .. current_branch
|
u.notify(string.format("This MR was merged %s", u.time_since(state.INFO.merged_at)), vim.log.levels.WARN)
|
||||||
end)
|
|
||||||
local remote_up_to_date = #current_head_on_remote == 1
|
|
||||||
|
|
||||||
if not remote_up_to_date then
|
|
||||||
require("gitlab.utils").notify(
|
|
||||||
string.format(
|
|
||||||
"You have local commits that are not on %s. Have you forgotten to push?",
|
|
||||||
state.settings.connection_settings.remote
|
|
||||||
),
|
|
||||||
log_level
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
return remote_up_to_date
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return M
|
return M
|
||||||
|
|||||||
@@ -62,18 +62,6 @@ M.open = function()
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
if state.INFO.has_conflicts then
|
|
||||||
u.notify("This merge request has conflicts!", vim.log.levels.WARN)
|
|
||||||
end
|
|
||||||
|
|
||||||
if state.INFO.state == "closed" then
|
|
||||||
u.notify(string.format("This MR was closed %s", u.time_since(state.INFO.closed_at)), vim.log.levels.WARN)
|
|
||||||
end
|
|
||||||
|
|
||||||
if state.INFO.state == "merged" then
|
|
||||||
u.notify(string.format("This MR was merged %s", u.time_since(state.INFO.merged_at)), vim.log.levels.WARN)
|
|
||||||
end
|
|
||||||
|
|
||||||
if state.settings.discussion_diagnostic ~= nil or state.settings.discussion_sign ~= nil then
|
if state.settings.discussion_diagnostic ~= nil or state.settings.discussion_sign ~= nil then
|
||||||
u.notify(
|
u.notify(
|
||||||
"Diagnostics are now configured as settings.discussion_signs, see :h gitlab.nvim.signs-and-diagnostics",
|
"Diagnostics are now configured as settings.discussion_signs, see :h gitlab.nvim.signs-and-diagnostics",
|
||||||
@@ -98,7 +86,8 @@ M.open = function()
|
|||||||
require("gitlab").toggle_discussions() -- Fetches data and opens discussions
|
require("gitlab").toggle_discussions() -- Fetches data and opens discussions
|
||||||
end
|
end
|
||||||
|
|
||||||
git.current_branch_up_to_date_on_remote(vim.log.levels.WARN)
|
git.check_current_branch_up_to_date_on_remote(vim.log.levels.WARN)
|
||||||
|
git.check_mr_in_good_condition()
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Closes the reviewer and cleans up
|
-- Closes the reviewer and cleans up
|
||||||
|
|||||||
@@ -20,10 +20,10 @@ M.start = function(callback)
|
|||||||
debug = state.settings.debug,
|
debug = state.settings.debug,
|
||||||
log_path = state.settings.log_path,
|
log_path = state.settings.log_path,
|
||||||
connection_settings = state.settings.connection_settings,
|
connection_settings = state.settings.connection_settings,
|
||||||
chosen_target_branch = state.chosen_target_branch,
|
chosen_mr_iid = state.chosen_mr_iid,
|
||||||
}
|
}
|
||||||
|
|
||||||
state.chosen_target_branch = nil -- Do not let this interfere with subsequent reviewer.open() calls
|
state.chosen_mr_iid = 0 -- Do not let this interfere with subsequent reviewer.open() calls
|
||||||
|
|
||||||
local settings = vim.json.encode(go_server_settings)
|
local settings = vim.json.encode(go_server_settings)
|
||||||
local command = string.format("%s '%s'", state.settings.bin, settings)
|
local command = string.format("%s '%s'", state.settings.bin, settings)
|
||||||
@@ -100,6 +100,7 @@ M.build = function(override)
|
|||||||
u.notify("Could not install gitlab.nvim!", vim.log.levels.ERROR)
|
u.notify("Could not install gitlab.nvim!", vim.log.levels.ERROR)
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
u.notify("Gitlab.nvim installed successfully!", vim.log.levels.INFO)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -251,9 +251,8 @@ M.unlinked_discussion_tree = {
|
|||||||
unresolved_expanded = false,
|
unresolved_expanded = false,
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Used to set a specific target when choosing a merge request, due to the fact
|
-- Used to set a specific MR when choosing a merge request
|
||||||
-- that it's technically possible to have multiple target branches
|
M.chosen_mr_iid = 0
|
||||||
M.chosen_target_branch = nil
|
|
||||||
|
|
||||||
-- These keymaps are set globally when the plugin is initialized
|
-- These keymaps are set globally when the plugin is initialized
|
||||||
M.set_global_keymaps = function()
|
M.set_global_keymaps = function()
|
||||||
|
|||||||
@@ -33,6 +33,23 @@ function List:filter(func)
|
|||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---Partitions a given list into two lists
|
||||||
|
---@generic T
|
||||||
|
---@param func fun(v: T, i: integer):boolean
|
||||||
|
---@return List<T>, List<T> @Returns two lists: the 1st with elements for which func returns true, the 2nd with elements for which it returns false
|
||||||
|
function List:partition(func)
|
||||||
|
local result_true = List.new()
|
||||||
|
local result_false = List.new()
|
||||||
|
for i, v in ipairs(self) do
|
||||||
|
if func(v, i) == true then
|
||||||
|
table.insert(result_true, v)
|
||||||
|
else
|
||||||
|
table.insert(result_false, v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return result_true, result_false
|
||||||
|
end
|
||||||
|
|
||||||
function List:reduce(func, agg)
|
function List:reduce(func, agg)
|
||||||
for i, v in ipairs(self) do
|
for i, v in ipairs(self) do
|
||||||
agg = func(agg, v, i)
|
agg = func(agg, v, i)
|
||||||
|
|||||||
Reference in New Issue
Block a user