2.0.0 (#196)
This MR is a #MAJOR breaking change to the plugin. While the plugin will continue to work for users with their existing settings, they will be informed of outdated configuration (diagnostics and signs have been simplified) the next time they open the reviewer. Fix: Trim trailing slash from custom URLs Update: .github/CONTRIBUTING.md, .github/ISSUE_TEMPLATE/bug_report.md Feat: Improve discussion tree toggling (#192) Fix: Toggle modified notes (#188) Fix: Toggle discussion nodes correctly Feat: Show Help keymap in discussion tree winbar Fix: Enable toggling nodes from the note body Fix: Enable toggling resolved status from child nodes Fix: Only try to show emoji popup on note nodes Feat: Add keymap for toggling tree type Fix: Disable tree type toggling in Notes Fix Multi Line Issues (Large Refactor) (#197) Fix: Multi-line discussions. The calculation of a range for a multiline comment has been consolidated and moved into the location.lua file. This does not attempt to fix diagnostics. Refactor: It refactors the discussions code to split hunk parsing and management into a separate module Fix: Don't allow comments on modified buffers #194 by preventing comments on the reviewer when using --imply-local and when the working tree is dirty entirely. Refactor: It introduces a new List class for data aggregation, filtering, etc. Fix: It removes redundant API calls and refreshes from the discussion pane Fix: Location provider (#198) Fix: add nil check for Diffview performance issue (#199) Fix: Switch Tabs During Comment Creation (#200) Fix: Check if file is modified (#201) Fix: Off-By-One Issue in Old SHA (#202) Fix: Rebuild Diagnostics + Signs (#203) Fix: Off-By-One Issue in New SHA (#205) Fix: Reviewer Jumps to wrong location (#206) BREAKING CHANGE: Changes configuration of diagnostics and signs in the setup call.
This commit is contained in:
committed by
GitHub
parent
f6a5238d4b
commit
b5b475ce8b
@@ -2,6 +2,7 @@
|
||||
-- and assignees in Gitlab, those who must review an MR.
|
||||
local u = require("gitlab.utils")
|
||||
local job = require("gitlab.job")
|
||||
local List = require("gitlab.utils.list")
|
||||
local state = require("gitlab.state")
|
||||
local M = {}
|
||||
|
||||
@@ -67,13 +68,11 @@ end
|
||||
|
||||
M.filter_eligible = function(current, to_remove)
|
||||
local ids = u.extract(to_remove, "id")
|
||||
local res = {}
|
||||
for _, member in ipairs(current) do
|
||||
return List.new(current):filter(function(member)
|
||||
if not u.contains(ids, member.id) then
|
||||
table.insert(res, member)
|
||||
return true
|
||||
end
|
||||
end
|
||||
return res
|
||||
end)
|
||||
end
|
||||
|
||||
return M
|
||||
|
||||
@@ -5,9 +5,11 @@ local Popup = require("nui.popup")
|
||||
local state = require("gitlab.state")
|
||||
local job = require("gitlab.job")
|
||||
local u = require("gitlab.utils")
|
||||
local git = require("gitlab.git")
|
||||
local discussions = require("gitlab.actions.discussions")
|
||||
local miscellaneous = require("gitlab.actions.miscellaneous")
|
||||
local reviewer = require("gitlab.reviewer")
|
||||
local Location = require("gitlab.reviewer.location")
|
||||
local M = {}
|
||||
|
||||
-- Popup creation is wrapped in a function so that it is performed *after* user
|
||||
@@ -20,6 +22,15 @@ end
|
||||
-- This function will open a comment popup in order to create a comment on the changed/updated
|
||||
-- line in the current MR
|
||||
M.create_comment = function()
|
||||
local has_clean_tree = git.has_clean_tree()
|
||||
local is_modified = vim.api.nvim_buf_get_option(0, "modified")
|
||||
if state.settings.reviewer_settings.diffview.imply_local and (is_modified or not has_clean_tree) then
|
||||
u.notify(
|
||||
"Cannot leave comments on changed files. \n Please stash all local changes or push them to the feature branch.",
|
||||
vim.log.levels.WARN
|
||||
)
|
||||
return
|
||||
end
|
||||
local comment_popup = create_comment_popup()
|
||||
comment_popup:mount()
|
||||
state.set_popup_keymaps(comment_popup, function(text)
|
||||
@@ -95,30 +106,11 @@ M.create_note = function()
|
||||
end, miscellaneous.attach_file)
|
||||
end
|
||||
|
||||
---@class LineRange
|
||||
---@field start_line integer
|
||||
---@field end_line integer
|
||||
|
||||
---@class ReviewerLineInfo
|
||||
---@field old_line integer
|
||||
---@field new_line integer
|
||||
---@field type string either "new" or "old"
|
||||
|
||||
---@class ReviewerRangeInfo
|
||||
---@field start ReviewerLineInfo
|
||||
---@field end ReviewerLineInfo
|
||||
|
||||
---@class ReviewerInfo
|
||||
---@field file_name string
|
||||
---@field old_line integer | nil
|
||||
---@field new_line integer | nil
|
||||
---@field range_info ReviewerRangeInfo|nil
|
||||
|
||||
---This function (settings.popup.perform_action) will send the comment to the Go server
|
||||
---@param text string comment text
|
||||
---@param range LineRange | nil range of visuel selection or nil
|
||||
---@param visual_range LineRange | nil range of visual selection or nil
|
||||
---@param unlinked boolean | nil if true, the comment is not linked to a line
|
||||
M.confirm_create_comment = function(text, range, unlinked)
|
||||
M.confirm_create_comment = function(text, visual_range, unlinked)
|
||||
if text == nil then
|
||||
u.notify("Reviewer did not provide text of change", vim.log.levels.ERROR)
|
||||
return
|
||||
@@ -129,33 +121,42 @@ M.confirm_create_comment = function(text, range, unlinked)
|
||||
job.run_job("/mr/comment", "POST", body, function(data)
|
||||
u.notify("Note created!", vim.log.levels.INFO)
|
||||
discussions.add_discussion({ data = data, unlinked = true })
|
||||
discussions.refresh_discussion_data()
|
||||
discussions.refresh()
|
||||
end)
|
||||
return
|
||||
end
|
||||
|
||||
local reviewer_info = reviewer.get_location(range)
|
||||
if not reviewer_info then
|
||||
local reviewer_data = reviewer.get_reviewer_data()
|
||||
if reviewer_data == nil then
|
||||
u.notify("Error getting reviewer data", vim.log.levels.ERROR)
|
||||
return
|
||||
end
|
||||
|
||||
local location = Location.new(reviewer_data, visual_range)
|
||||
location:build_location_data()
|
||||
local location_data = location.location_data
|
||||
if location_data == nil then
|
||||
u.notify("Error getting location information", vim.log.levels.ERROR)
|
||||
return
|
||||
end
|
||||
|
||||
local revision = state.MR_REVISIONS[1]
|
||||
local body = {
|
||||
type = "text",
|
||||
comment = text,
|
||||
file_name = reviewer_info.file_name,
|
||||
old_line = reviewer_info.old_line,
|
||||
new_line = reviewer_info.new_line,
|
||||
file_name = reviewer_data.file_name,
|
||||
base_commit_sha = revision.base_commit_sha,
|
||||
start_commit_sha = revision.start_commit_sha,
|
||||
head_commit_sha = revision.head_commit_sha,
|
||||
type = "text",
|
||||
line_range = reviewer_info.range_info,
|
||||
old_line = location_data.old_line,
|
||||
new_line = location_data.new_line,
|
||||
line_range = location_data.line_range,
|
||||
}
|
||||
|
||||
job.run_job("/mr/comment", "POST", body, function(data)
|
||||
u.notify("Comment created!", vim.log.levels.INFO)
|
||||
discussions.add_discussion({ data = data, unlinked = false })
|
||||
discussions.refresh_discussion_data()
|
||||
discussions.refresh()
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ local Input = require("nui.input")
|
||||
local Popup = require("nui.popup")
|
||||
local job = require("gitlab.job")
|
||||
local u = require("gitlab.utils")
|
||||
local git = require("gitlab.git")
|
||||
local state = require("gitlab.state")
|
||||
local miscellaneous = require("gitlab.actions.miscellaneous")
|
||||
|
||||
@@ -124,7 +125,7 @@ M.pick_target = function(args)
|
||||
end
|
||||
|
||||
local function make_template_path(t)
|
||||
local base_dir = vim.fn.trim(vim.fn.system({ "git", "rev-parse", "--show-toplevel" }))
|
||||
local base_dir = git.base_dir()
|
||||
return base_dir
|
||||
.. state.settings.file_separator
|
||||
.. ".gitlab"
|
||||
|
||||
@@ -101,3 +101,22 @@
|
||||
---@field user_data table
|
||||
---@field source string
|
||||
---@field code string?
|
||||
|
||||
---@class LineRange
|
||||
---@field start_line integer
|
||||
---@field end_line integer
|
||||
|
||||
---@class DiffviewInfo
|
||||
---@field modification_type string
|
||||
---@field file_name string
|
||||
---@field current_bufnr integer
|
||||
---@field new_sha_win_id integer
|
||||
---@field old_sha_win_id integer
|
||||
---@field opposite_bufnr integer
|
||||
---@field new_line_from_buf integer
|
||||
---@field old_line_from_buf integer
|
||||
|
||||
---@class LocationData
|
||||
---@field old_line integer | nil
|
||||
---@field new_line integer | nil
|
||||
---@field line_range ReviewerRangeInfo|nil
|
||||
|
||||
@@ -9,9 +9,13 @@ local job = require("gitlab.job")
|
||||
local u = require("gitlab.utils")
|
||||
local state = require("gitlab.state")
|
||||
local reviewer = require("gitlab.reviewer")
|
||||
local List = require("gitlab.utils.list")
|
||||
local miscellaneous = require("gitlab.actions.miscellaneous")
|
||||
local discussions_tree = require("gitlab.actions.discussions.tree")
|
||||
local signs = require("gitlab.actions.discussions.signs")
|
||||
local diffview_lib = require("diffview.lib")
|
||||
local common = require("gitlab.indicators.common")
|
||||
local signs = require("gitlab.indicators.signs")
|
||||
local diagnostics = require("gitlab.indicators.diagnostics")
|
||||
local winbar = require("gitlab.actions.discussions.winbar")
|
||||
local help = require("gitlab.actions.help")
|
||||
local emoji = require("gitlab.emoji")
|
||||
@@ -53,28 +57,68 @@ end
|
||||
---Initialize everything for discussions like setup of signs, callbacks for reviewer, etc.
|
||||
M.initialize_discussions = function()
|
||||
signs.setup_signs()
|
||||
-- Setup callback to refresh discussion data, discussion signs and diagnostics whenever the reviewed file changes.
|
||||
reviewer.set_callback_for_file_changed(M.refresh_discussion_data)
|
||||
-- Setup callback to clear signs and diagnostics whenever reviewer is left.
|
||||
reviewer.set_callback_for_reviewer_leave(signs.clear_signs_and_diagnostics)
|
||||
reviewer.set_callback_for_file_changed(function()
|
||||
M.refresh_view()
|
||||
M.modifiable(false)
|
||||
end)
|
||||
reviewer.set_callback_for_reviewer_enter(function()
|
||||
M.modifiable(false)
|
||||
end)
|
||||
reviewer.set_callback_for_reviewer_leave(function()
|
||||
signs.clear_signs()
|
||||
diagnostics.clear_diagnostics()
|
||||
M.modifiable(true)
|
||||
end)
|
||||
end
|
||||
|
||||
--- Ensures that the both buffers in the reviewer are/not modifiable. Relevant if the user is using
|
||||
--- the --imply-local setting
|
||||
M.modifiable = function(bool)
|
||||
local view = diffview_lib.get_current_view()
|
||||
local a = view.cur_layout.a.file.bufnr
|
||||
local b = view.cur_layout.b.file.bufnr
|
||||
if a ~= nil and vim.api.nvim_buf_is_loaded(a) then
|
||||
vim.api.nvim_buf_set_option(a, "modifiable", bool)
|
||||
end
|
||||
if b ~= nil and vim.api.nvim_buf_is_loaded(b) then
|
||||
vim.api.nvim_buf_set_option(b, "modifiable", bool)
|
||||
end
|
||||
end
|
||||
|
||||
---Refresh discussion data, signs, diagnostics, and winbar with new data from API
|
||||
M.refresh_discussion_data = function()
|
||||
--- and rebuild the entire view
|
||||
M.refresh = function()
|
||||
M.load_discussions(function()
|
||||
if state.settings.discussion_sign.enabled then
|
||||
signs.refresh_signs(M.discussions)
|
||||
end
|
||||
if state.settings.discussion_diagnostic.enabled then
|
||||
signs.refresh_diagnostics(M.discussions)
|
||||
end
|
||||
if M.split_visible then
|
||||
local linked_is_focused = M.linked_bufnr == M.focused_bufnr
|
||||
winbar.update_winbar(M.discussions, M.unlinked_discussions, linked_is_focused and "Discussions" or "Notes")
|
||||
end
|
||||
M.refresh_view()
|
||||
end)
|
||||
end
|
||||
|
||||
--- Take existing data and refresh the diagnostics, the winbar, and the signs
|
||||
M.refresh_view = function()
|
||||
if state.settings.discussion_signs.enabled then
|
||||
diagnostics.refresh_diagnostics(M.discussions)
|
||||
end
|
||||
if M.split_visible then
|
||||
local linked_is_focused = M.linked_bufnr == M.focused_bufnr
|
||||
winbar.update_winbar(M.discussions, M.unlinked_discussions, linked_is_focused and "Discussions" or "Notes")
|
||||
end
|
||||
end
|
||||
|
||||
---Toggle Discussions tree type between "simple" and "by_file_name"
|
||||
---@param unlinked boolean True if selected view type is Notes (unlinked discussions)
|
||||
M.toggle_tree_type = function(unlinked)
|
||||
if unlinked then
|
||||
u.notify("Toggling tree type is only possible in Discussions", vim.log.levels.INFO)
|
||||
return
|
||||
end
|
||||
if state.settings.discussion_tree.tree_type == "simple" then
|
||||
state.settings.discussion_tree.tree_type = "by_file_name"
|
||||
else
|
||||
state.settings.discussion_tree.tree_type = "simple"
|
||||
end
|
||||
M.rebuild_discussion_tree()
|
||||
end
|
||||
|
||||
---Opens the discussion tree, sets the keybindings. It also
|
||||
---creates the tree for notes (which are not linked to specific lines of code)
|
||||
---@param callback function?
|
||||
@@ -124,7 +168,7 @@ M.toggle = function(callback)
|
||||
M.focused_bufnr = default_buffer
|
||||
|
||||
M.switch_can_edit_bufs(false)
|
||||
winbar.update_winbar(M.discussions, M.unlinked_discussions, default_discussions and "Discussions" or "Notes")
|
||||
M.refresh_view()
|
||||
|
||||
vim.api.nvim_set_current_win(current_window)
|
||||
if type(callback) == "function" then
|
||||
@@ -133,6 +177,7 @@ M.toggle = function(callback)
|
||||
end)
|
||||
end
|
||||
|
||||
-- Change between views in the discussion panel, either notes or discussions
|
||||
local switch_view_type = function()
|
||||
local change_to_unlinked = M.linked_bufnr == M.focused_bufnr
|
||||
local new_bufnr = change_to_unlinked and M.unlinked_bufnr or M.linked_bufnr
|
||||
@@ -153,7 +198,7 @@ end
|
||||
---Move to the discussion tree at the discussion from diagnostic on current line.
|
||||
M.move_to_discussion_tree = function()
|
||||
local current_line = vim.api.nvim_win_get_cursor(0)[1]
|
||||
local diagnostics = vim.diagnostic.get(0, { namespace = signs.diagnostics_namespace, lnum = current_line - 1 })
|
||||
local d = vim.diagnostic.get(0, { namespace = diagnostics.diagnostics_namespace, lnum = current_line - 1 })
|
||||
|
||||
---Function used to jump to the discussion tree after the menu selection.
|
||||
local jump_after_menu_selection = function(diagnostic)
|
||||
@@ -184,11 +229,11 @@ M.move_to_discussion_tree = function()
|
||||
end
|
||||
end
|
||||
|
||||
if #diagnostics == 0 then
|
||||
if #d == 0 then
|
||||
u.notify("No diagnostics for this line", vim.log.levels.WARN)
|
||||
return
|
||||
elseif #diagnostics > 1 then
|
||||
vim.ui.select(diagnostics, {
|
||||
elseif #d > 1 then
|
||||
vim.ui.select(d, {
|
||||
prompt = "Choose discussion to jump to",
|
||||
format_item = function(diagnostic)
|
||||
return diagnostic.message
|
||||
@@ -200,7 +245,7 @@ M.move_to_discussion_tree = function()
|
||||
jump_after_menu_selection(diagnostic)
|
||||
end)
|
||||
else
|
||||
jump_after_menu_selection(diagnostics[1])
|
||||
jump_after_menu_selection(d[1])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -239,36 +284,23 @@ end
|
||||
|
||||
-- This function will actually send the deletion to Gitlab
|
||||
-- when you make a selection, and re-render the tree
|
||||
M.send_deletion = function(tree, unlinked)
|
||||
M.send_deletion = function(tree)
|
||||
local current_node = tree:get_node()
|
||||
|
||||
local note_node = M.get_note_node(tree, current_node)
|
||||
local root_node = M.get_root_node(tree, current_node)
|
||||
local note_id = note_node.is_root and root_node.root_note_id or note_node.id
|
||||
|
||||
local body = { discussion_id = root_node.id, note_id = tonumber(note_id) }
|
||||
|
||||
job.run_job("/mr/comment", "DELETE", body, function(data)
|
||||
u.notify(data.message, vim.log.levels.INFO)
|
||||
if not note_node.is_root then
|
||||
tree:remove_node("-" .. note_id) -- Note is not a discussion root, safe to remove
|
||||
tree:render()
|
||||
if note_node.is_root then
|
||||
-- Replace root node w/ current node's contents...
|
||||
tree:remove_node("-" .. root_node.id)
|
||||
else
|
||||
if unlinked then
|
||||
M.unlinked_discussions = u.remove_first_value(M.unlinked_discussions)
|
||||
M.rebuild_unlinked_discussion_tree()
|
||||
else
|
||||
M.discussions = u.remove_first_value(M.discussions)
|
||||
M.rebuild_discussion_tree()
|
||||
end
|
||||
M.add_empty_titles({
|
||||
{ M.linked_bufnr, M.discussions, "No Discussions for this MR" },
|
||||
{ M.unlinked_bufnr, M.unlinked_discussions, "No Notes (Unlinked Discussions) for this MR" },
|
||||
})
|
||||
M.switch_can_edit_bufs(false)
|
||||
tree:remove_node("-" .. note_id)
|
||||
end
|
||||
|
||||
M.refresh_discussion_data()
|
||||
tree:render()
|
||||
M.refresh()
|
||||
end)
|
||||
end
|
||||
|
||||
@@ -278,18 +310,22 @@ M.edit_comment = function(tree, unlinked)
|
||||
local current_node = tree:get_node()
|
||||
local note_node = M.get_note_node(tree, current_node)
|
||||
local root_node = M.get_root_node(tree, current_node)
|
||||
if note_node == nil or root_node == nil then
|
||||
u.notify("Could not get root or note node", vim.log.levels.ERROR)
|
||||
return
|
||||
end
|
||||
|
||||
edit_popup:mount()
|
||||
|
||||
local lines = {} -- Gather all lines from immediate children that aren't note nodes
|
||||
local children_ids = note_node:get_child_ids()
|
||||
for _, child_id in ipairs(children_ids) do
|
||||
-- Gather all lines from immediate children that aren't note nodes
|
||||
local lines = List.new(note_node:get_child_ids()):reduce(function(agg, child_id)
|
||||
local child_node = tree:get_node(child_id)
|
||||
if not child_node:has_children() then
|
||||
local line = tree:get_node(child_id).text
|
||||
table.insert(lines, line)
|
||||
table.insert(agg, line)
|
||||
end
|
||||
end
|
||||
return agg
|
||||
end, {})
|
||||
|
||||
local currentBuffer = vim.api.nvim_get_current_buf()
|
||||
vim.api.nvim_buf_set_lines(currentBuffer, 0, -1, false, lines)
|
||||
@@ -327,7 +363,15 @@ end
|
||||
-- This function (settings.discussion_tree.toggle_discussion_resolved) will toggle the resolved status of the current discussion and send the change to the Go server
|
||||
M.toggle_discussion_resolved = function(tree)
|
||||
local note = tree:get_node()
|
||||
if not note or not note.resolvable then
|
||||
if note == nil then
|
||||
return
|
||||
end
|
||||
|
||||
-- Switch to the root node to enable toggling from child nodes and note bodies
|
||||
if not note.resolvable and M.is_node_note(note) then
|
||||
note = M.get_root_node(tree, note)
|
||||
end
|
||||
if note == nil then
|
||||
return
|
||||
end
|
||||
|
||||
@@ -339,29 +383,86 @@ M.toggle_discussion_resolved = function(tree)
|
||||
job.run_job("/mr/discussions/resolve", "PUT", body, function(data)
|
||||
u.notify(data.message, vim.log.levels.INFO)
|
||||
M.redraw_resolved_status(tree, note, not note.resolved)
|
||||
M.refresh_discussion_data()
|
||||
M.refresh()
|
||||
end)
|
||||
end
|
||||
|
||||
---Takes a node and returns the line where the note is positioned in the new SHA. If
|
||||
---the line is not in the new SHA, returns nil
|
||||
---@param node any
|
||||
---@return number|nil
|
||||
local function get_new_line(node)
|
||||
if node.new_line == nil then
|
||||
return nil
|
||||
end
|
||||
|
||||
---@type GitlabLineRange|nil
|
||||
local range = node.range
|
||||
if range == nil then
|
||||
if node.new_line == nil then
|
||||
return nil
|
||||
end
|
||||
return node.new_line
|
||||
end
|
||||
|
||||
local start_new_line, _ = common.parse_line_code(range.start.line_code)
|
||||
return start_new_line
|
||||
end
|
||||
|
||||
---Takes a node and returns the line where the note is positioned in the old SHA. If
|
||||
---the line is not in the old SHA, returns nil
|
||||
---@param node any
|
||||
---@return number|nil
|
||||
local function get_old_line(node)
|
||||
if node.old_line == nil then
|
||||
return nil
|
||||
end
|
||||
|
||||
---@type GitlabLineRange|nil
|
||||
local range = node.range
|
||||
if range == nil then
|
||||
return node.old_line
|
||||
end
|
||||
|
||||
local _, start_old_line = common.parse_line_code(range.start.line_code)
|
||||
return start_old_line
|
||||
end
|
||||
|
||||
-- This function (settings.discussion_tree.jump_to_reviewer) will jump the cursor to the reviewer's location associated with the note. The implementation depends on the reviewer
|
||||
M.jump_to_reviewer = function(tree)
|
||||
local file_name, new_line, old_line, is_undefined_type, error = M.get_note_location(tree)
|
||||
if error ~= nil then
|
||||
u.notify(error, vim.log.levels.ERROR)
|
||||
local node = tree:get_node()
|
||||
local root_node = M.get_root_node(tree, node)
|
||||
if root_node == nil then
|
||||
u.notify("Could not get discussion node", vim.log.levels.ERROR)
|
||||
return
|
||||
end
|
||||
reviewer.jump(file_name, new_line, old_line, { is_undefined_type = is_undefined_type })
|
||||
reviewer.jump(root_node.file_name, get_new_line(root_node), get_old_line(root_node))
|
||||
M.refresh_view()
|
||||
end
|
||||
|
||||
-- This function (settings.discussion_tree.jump_to_file) will jump to the file changed in a new tab
|
||||
M.jump_to_file = function(tree)
|
||||
local file_name, new_line, old_line, _, error = M.get_note_location(tree)
|
||||
if error ~= nil then
|
||||
u.notify(error, vim.log.levels.ERROR)
|
||||
local node = tree:get_node()
|
||||
local root_node = M.get_root_node(tree, node)
|
||||
if root_node == nil then
|
||||
u.notify("Could not get discussion node", vim.log.levels.ERROR)
|
||||
return
|
||||
end
|
||||
vim.cmd.tabnew()
|
||||
u.jump_to_file(file_name, (new_line or old_line))
|
||||
local line_number = get_new_line(root_node) or get_old_line(root_node)
|
||||
if line_number == nil then
|
||||
line_number = 1
|
||||
end
|
||||
local bufnr = vim.fn.bufnr(root_node.filename)
|
||||
if bufnr ~= -1 then
|
||||
vim.cmd("buffer " .. bufnr)
|
||||
vim.api.nvim_win_set_cursor(0, { line_number, 0 })
|
||||
return
|
||||
end
|
||||
|
||||
-- If buffer is not already open, open it
|
||||
vim.cmd("edit " .. root_node.filename)
|
||||
vim.api.nvim_win_set_cursor(0, { line_number, 0 })
|
||||
end
|
||||
|
||||
-- This function (settings.discussion_tree.toggle_node) expands/collapses the current node and its children
|
||||
@@ -370,6 +471,15 @@ M.toggle_node = function(tree)
|
||||
if node == nil then
|
||||
return
|
||||
end
|
||||
|
||||
-- Switch to the "note" node from "note_body" nodes to enable toggling discussions inside comments
|
||||
if node.type == "note_body" then
|
||||
node = tree:get_node(node:get_parent_id())
|
||||
end
|
||||
if node == nil then
|
||||
return
|
||||
end
|
||||
|
||||
local children = node:get_child_ids()
|
||||
if node == nil then
|
||||
return
|
||||
@@ -663,6 +773,9 @@ M.is_current_node_note = function(tree)
|
||||
end
|
||||
|
||||
M.set_tree_keymaps = function(tree, bufnr, unlinked)
|
||||
vim.keymap.set("n", state.settings.discussion_tree.toggle_tree_type, function()
|
||||
M.toggle_tree_type(unlinked)
|
||||
end, { buffer = bufnr, desc = "Toggle tree type between `simple` and `by_file_name`" })
|
||||
vim.keymap.set("n", state.settings.discussion_tree.edit_comment, function()
|
||||
if M.is_current_node_note(tree) then
|
||||
M.edit_comment(tree, unlinked)
|
||||
@@ -843,25 +956,6 @@ M.add_reply_to_tree = function(tree, note, discussion_id)
|
||||
tree:render()
|
||||
end
|
||||
|
||||
---Get note location
|
||||
---@param tree NuiTree
|
||||
---@return string, string, string, boolean, string?
|
||||
M.get_note_location = function(tree)
|
||||
local node = tree:get_node()
|
||||
if node == nil then
|
||||
return "", "", "", false, "Could not get node"
|
||||
end
|
||||
local discussion_node = M.get_root_node(tree, node)
|
||||
if discussion_node == nil then
|
||||
return "", "", "", false, "Could not get discussion node"
|
||||
end
|
||||
return discussion_node.file_name,
|
||||
discussion_node.new_line,
|
||||
discussion_node.old_line,
|
||||
discussion_node.undefined_type or false,
|
||||
nil
|
||||
end
|
||||
|
||||
---@param tree NuiTree
|
||||
M.open_in_browser = function(tree)
|
||||
local current_node = tree:get_node()
|
||||
|
||||
@@ -1,336 +0,0 @@
|
||||
local state = require("gitlab.state")
|
||||
local u = require("gitlab.utils")
|
||||
local reviewer = require("gitlab.reviewer")
|
||||
local discussion_sign_name = "gitlab_discussion"
|
||||
local discussion_helper_sign_start = "gitlab_discussion_helper_start"
|
||||
local discussion_helper_sign_mid = "gitlab_discussion_helper_mid"
|
||||
local discussion_helper_sign_end = "gitlab_discussion_helper_end"
|
||||
local diagnostics_namespace = vim.api.nvim_create_namespace(discussion_sign_name)
|
||||
|
||||
local M = {}
|
||||
M.diagnostics_namespace = diagnostics_namespace
|
||||
|
||||
---Clear all signs and diagnostics
|
||||
M.clear_signs_and_diagnostics = function()
|
||||
vim.fn.sign_unplace(discussion_sign_name)
|
||||
vim.diagnostic.reset(diagnostics_namespace)
|
||||
end
|
||||
|
||||
---Refresh the discussion signs for currently loaded file in reviewer For convinience we use same
|
||||
---string for sign name and sign group ( currently there is only one sign needed)
|
||||
---@param discussions Discussion[]
|
||||
M.refresh_signs = function(discussions)
|
||||
local filtered_discussions = M.filter_discussions_for_signs_and_diagnostics(discussions)
|
||||
if filtered_discussions == nil then
|
||||
vim.diagnostic.reset(diagnostics_namespace)
|
||||
return
|
||||
end
|
||||
|
||||
local new_signs, old_signs, error = M.parse_signs_from_discussions(filtered_discussions)
|
||||
if error ~= nil then
|
||||
vim.notify(error, vim.log.levels.ERROR)
|
||||
return
|
||||
end
|
||||
|
||||
vim.fn.sign_unplace(discussion_sign_name)
|
||||
reviewer.place_sign(old_signs, "old")
|
||||
reviewer.place_sign(new_signs, "new")
|
||||
end
|
||||
|
||||
---Refresh the diagnostics for the currently reviewed file
|
||||
---@param discussions Discussion[]
|
||||
M.refresh_diagnostics = function(discussions)
|
||||
-- Keep in mind that diagnostic line numbers use 0-based indexing while line numbers use
|
||||
-- 1-based indexing
|
||||
local filtered_discussions = M.filter_discussions_for_signs_and_diagnostics(discussions)
|
||||
if filtered_discussions == nil then
|
||||
vim.diagnostic.reset(diagnostics_namespace)
|
||||
return
|
||||
end
|
||||
|
||||
local new_diagnostics, old_diagnostics = M.parse_diagnostics_from_discussions(filtered_discussions)
|
||||
|
||||
vim.diagnostic.reset(diagnostics_namespace)
|
||||
reviewer.set_diagnostics(
|
||||
diagnostics_namespace,
|
||||
new_diagnostics,
|
||||
"new",
|
||||
state.settings.discussion_diagnostic.display_opts
|
||||
)
|
||||
reviewer.set_diagnostics(
|
||||
diagnostics_namespace,
|
||||
old_diagnostics,
|
||||
"old",
|
||||
state.settings.discussion_diagnostic.display_opts
|
||||
)
|
||||
end
|
||||
|
||||
---Filter all discussions which are relevant for currently visible signs and diagnostscs.
|
||||
---@return Discussion[]?
|
||||
M.filter_discussions_for_signs_and_diagnostics = function(all_discussions)
|
||||
if type(all_discussions) ~= "table" then
|
||||
return
|
||||
end
|
||||
local file = reviewer.get_current_file()
|
||||
if not file then
|
||||
return
|
||||
end
|
||||
local discussions = {}
|
||||
for _, discussion in ipairs(all_discussions) do
|
||||
local first_note = discussion.notes[1]
|
||||
if
|
||||
type(first_note.position) == "table"
|
||||
and (first_note.position.new_path == file or first_note.position.old_path == file)
|
||||
then
|
||||
if
|
||||
--Skip resolved discussions
|
||||
not (
|
||||
state.settings.discussion_sign_and_diagnostic.skip_resolved_discussion
|
||||
and first_note.resolvable
|
||||
and first_note.resolved
|
||||
)
|
||||
--Skip discussions from old revisions
|
||||
and not (
|
||||
state.settings.discussion_sign_and_diagnostic.skip_old_revision_discussion
|
||||
and u.from_iso_format_date_to_timestamp(first_note.created_at)
|
||||
<= u.from_iso_format_date_to_timestamp(state.MR_REVISIONS[1].created_at)
|
||||
)
|
||||
then
|
||||
table.insert(discussions, discussion)
|
||||
end
|
||||
end
|
||||
end
|
||||
return discussions
|
||||
end
|
||||
|
||||
---Define signs for discussions if not already defined
|
||||
M.setup_signs = function()
|
||||
local discussion_sign = state.settings.discussion_sign
|
||||
local signs = {
|
||||
[discussion_sign_name] = discussion_sign.text,
|
||||
[discussion_helper_sign_start] = discussion_sign.helper_signs.start,
|
||||
[discussion_helper_sign_mid] = discussion_sign.helper_signs.mid,
|
||||
[discussion_helper_sign_end] = discussion_sign.helper_signs["end"],
|
||||
}
|
||||
for sign_name, sign_text in pairs(signs) do
|
||||
if #vim.fn.sign_getdefined(sign_name) == 0 then
|
||||
vim.fn.sign_define(sign_name, {
|
||||
text = sign_text,
|
||||
linehl = discussion_sign.linehl,
|
||||
texthl = discussion_sign.texthl,
|
||||
culhl = discussion_sign.culhl,
|
||||
numhl = discussion_sign.numhl,
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---Iterates over each discussion and returns a list of tables with sign
|
||||
---data, for instance group, priority, line number etc.
|
||||
---@param discussions Discussion[]
|
||||
---@return DiagnosticTable[], DiagnosticTable[], string?
|
||||
M.parse_diagnostics_from_discussions = function(discussions)
|
||||
local new_diagnostics = {}
|
||||
local old_diagnostics = {}
|
||||
for _, discussion in ipairs(discussions) do
|
||||
local first_note = discussion.notes[1]
|
||||
local message = ""
|
||||
for _, note in ipairs(discussion.notes) do
|
||||
message = message .. M.build_note_header(note) .. "\n" .. note.body .. "\n"
|
||||
end
|
||||
|
||||
local diagnostic = {
|
||||
message = message,
|
||||
col = 0,
|
||||
severity = state.settings.discussion_diagnostic.severity,
|
||||
user_data = { discussion_id = discussion.id, header = M.build_note_header(discussion.notes[1]) },
|
||||
source = "gitlab",
|
||||
code = state.settings.discussion_diagnostic.code,
|
||||
}
|
||||
|
||||
-- Diagnostics for line range discussions are tricky - you need to set lnum to be the
|
||||
-- line number equal to note.position.new_line or note.position.old_line because that is the
|
||||
-- only line where you can trigger the diagnostic to show. This also needs to be in sync
|
||||
-- with the sign placement.
|
||||
local line_range = first_note.position.line_range
|
||||
if line_range ~= nil then
|
||||
local start_old_line, start_new_line = M.parse_line_code(line_range.start.line_code)
|
||||
local end_old_line, end_new_line = M.parse_line_code(line_range["end"].line_code)
|
||||
|
||||
local start_type = line_range.start.type
|
||||
if start_type == "new" then
|
||||
local new_diagnostic
|
||||
if first_note.position.new_line == start_new_line then
|
||||
new_diagnostic = {
|
||||
lnum = start_new_line - 1,
|
||||
end_lnum = end_new_line - 1,
|
||||
}
|
||||
else
|
||||
new_diagnostic = {
|
||||
lnum = end_new_line - 1,
|
||||
end_lnum = start_new_line - 1,
|
||||
}
|
||||
end
|
||||
new_diagnostic = vim.tbl_deep_extend("force", new_diagnostic, diagnostic)
|
||||
table.insert(new_diagnostics, new_diagnostic)
|
||||
elseif start_type == "old" or start_type == "expanded" or start_type == "" then
|
||||
local old_diagnostic
|
||||
if first_note.position.old_line == start_old_line then
|
||||
old_diagnostic = {
|
||||
lnum = start_old_line - 1,
|
||||
end_lnum = end_old_line - 1,
|
||||
}
|
||||
else
|
||||
old_diagnostic = {
|
||||
lnum = end_old_line - 1,
|
||||
end_lnum = start_old_line - 1,
|
||||
}
|
||||
end
|
||||
old_diagnostic = vim.tbl_deep_extend("force", old_diagnostic, diagnostic)
|
||||
table.insert(old_diagnostics, old_diagnostic)
|
||||
else -- Comments on expanded, non-changed lines
|
||||
return {}, {}, string.format("Unsupported line range type found for discussion %s", discussion.id)
|
||||
end
|
||||
else -- Diagnostics for single line discussions.
|
||||
if first_note.position.new_line ~= nil and first_note.position.old_line == nil then
|
||||
local new_diagnostic = {
|
||||
lnum = first_note.position.new_line - 1,
|
||||
}
|
||||
new_diagnostic = vim.tbl_deep_extend("force", new_diagnostic, diagnostic)
|
||||
table.insert(new_diagnostics, new_diagnostic)
|
||||
end
|
||||
if first_note.position.old_line ~= nil then
|
||||
local old_diagnostic = {
|
||||
lnum = first_note.position.old_line - 1,
|
||||
}
|
||||
old_diagnostic = vim.tbl_deep_extend("force", old_diagnostic, diagnostic)
|
||||
table.insert(old_diagnostics, old_diagnostic)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return new_diagnostics, old_diagnostics
|
||||
end
|
||||
|
||||
local base_sign = {
|
||||
name = discussion_sign_name,
|
||||
group = discussion_sign_name,
|
||||
priority = state.settings.discussion_sign.priority,
|
||||
buffer = nil,
|
||||
}
|
||||
local base_helper_sign = {
|
||||
name = discussion_sign_name,
|
||||
group = discussion_sign_name,
|
||||
priority = state.settings.discussion_sign.priority - 1,
|
||||
buffer = nil,
|
||||
}
|
||||
|
||||
---Iterates over each discussion and returns a list of tables with sign
|
||||
---data, for instance group, priority, line number etc.
|
||||
---@param discussions Discussion[]
|
||||
---@return SignTable[], SignTable[], string?
|
||||
M.parse_signs_from_discussions = function(discussions)
|
||||
local new_signs = {}
|
||||
local old_signs = {}
|
||||
for _, discussion in ipairs(discussions) do
|
||||
local first_note = discussion.notes[1]
|
||||
local line_range = first_note.position.line_range
|
||||
|
||||
-- We have a line range which means we either have a multi-line comment or a comment
|
||||
-- on a line in an "expanded" part of a file
|
||||
if line_range ~= nil then
|
||||
local start_old_line, start_new_line = M.parse_line_code(line_range.start.line_code)
|
||||
local end_old_line, end_new_line = M.parse_line_code(line_range["end"].line_code)
|
||||
local discussion_line, start_line, end_line
|
||||
|
||||
local start_type = line_range.start.type
|
||||
if start_type == "new" then
|
||||
table.insert(
|
||||
new_signs,
|
||||
vim.tbl_deep_extend("force", {
|
||||
id = first_note.id,
|
||||
lnum = first_note.position.new_line,
|
||||
}, base_sign)
|
||||
)
|
||||
discussion_line = first_note.position.new_line
|
||||
start_line = start_new_line
|
||||
end_line = end_new_line
|
||||
elseif start_type == "old" or start_type == "expanded" or start_type == "" then
|
||||
table.insert(
|
||||
old_signs,
|
||||
vim.tbl_deep_extend("force", {
|
||||
id = first_note.id,
|
||||
lnum = first_note.position.old_line,
|
||||
}, base_sign)
|
||||
)
|
||||
discussion_line = first_note.position.old_line
|
||||
start_line = start_old_line
|
||||
end_line = end_old_line
|
||||
else
|
||||
return {}, {}, string.format("Unsupported line range type found for discussion %s", discussion.id)
|
||||
end
|
||||
|
||||
-- Helper signs does not have specific ids currently.
|
||||
if state.settings.discussion_sign.helper_signs.enabled then
|
||||
local helper_signs = {}
|
||||
if start_line > end_line then
|
||||
start_line, end_line = end_line, start_line
|
||||
end
|
||||
for i = start_line, end_line do
|
||||
if i ~= discussion_line then
|
||||
local sign_name
|
||||
if i == start_line then
|
||||
sign_name = discussion_helper_sign_start
|
||||
elseif i == end_line then
|
||||
sign_name = discussion_helper_sign_end
|
||||
else
|
||||
sign_name = discussion_helper_sign_mid
|
||||
end
|
||||
table.insert(
|
||||
helper_signs,
|
||||
vim.tbl_deep_extend("keep", {
|
||||
name = sign_name,
|
||||
lnum = i,
|
||||
}, base_helper_sign)
|
||||
)
|
||||
end
|
||||
end
|
||||
if start_type == "new" then
|
||||
vim.list_extend(new_signs, helper_signs)
|
||||
elseif start_type == "old" or start_type == "expanded" or start_type == "" then
|
||||
vim.list_extend(old_signs, helper_signs)
|
||||
end
|
||||
end
|
||||
else -- The note is a normal comment, not a range comment
|
||||
local sign = vim.tbl_deep_extend("force", {
|
||||
id = first_note.id,
|
||||
}, base_sign)
|
||||
if first_note.position.new_line ~= nil and first_note.position.old_line == nil then
|
||||
table.insert(new_signs, vim.tbl_deep_extend("force", { lnum = first_note.position.new_line }, sign))
|
||||
end
|
||||
if first_note.position.old_line ~= nil then
|
||||
table.insert(old_signs, vim.tbl_deep_extend("force", { lnum = first_note.position.old_line }, sign))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return new_signs, old_signs, nil
|
||||
end
|
||||
|
||||
---Parse line code and return old and new line numbers
|
||||
---@param line_code string gitlab line code -> 588440f66559714280628a4f9799f0c4eb880a4a_10_10
|
||||
---@return number?
|
||||
M.parse_line_code = function(line_code)
|
||||
local line_code_regex = "%w+_(%d+)_(%d+)"
|
||||
local old_line, new_line = line_code:match(line_code_regex)
|
||||
return tonumber(old_line), tonumber(new_line)
|
||||
end
|
||||
|
||||
---Build note header from note.
|
||||
---@param note Note
|
||||
---@return string
|
||||
M.build_note_header = function(note)
|
||||
return "@" .. note.author.username .. " " .. u.time_since(note.created_at)
|
||||
end
|
||||
|
||||
return M
|
||||
@@ -81,7 +81,7 @@ end
|
||||
---Build note header from note.
|
||||
---@param note Note
|
||||
---@return string
|
||||
local function build_note_header(note)
|
||||
M.build_note_header = function(note)
|
||||
return "@" .. note.author.username .. " " .. u.time_since(note.created_at)
|
||||
end
|
||||
|
||||
@@ -112,7 +112,7 @@ local function build_note_body(note, resolve_info)
|
||||
or state.settings.discussion_tree.unresolved
|
||||
end
|
||||
|
||||
local noteHeader = build_note_header(note) .. " " .. resolve_symbol
|
||||
local noteHeader = M.build_note_header(note) .. " " .. resolve_symbol
|
||||
|
||||
return noteHeader, text_nodes
|
||||
end
|
||||
@@ -158,8 +158,9 @@ M.add_discussions_to_table = function(items, unlinked)
|
||||
local root_id
|
||||
local root_text_nodes = {}
|
||||
local resolvable = false
|
||||
---@type GitlabLineRange|nil
|
||||
local range = nil
|
||||
local resolved = false
|
||||
local undefined_type = false
|
||||
local root_new_line = nil
|
||||
local root_old_line = nil
|
||||
local root_url
|
||||
@@ -175,16 +176,7 @@ M.add_discussions_to_table = function(items, unlinked)
|
||||
resolvable = note.resolvable
|
||||
resolved = note.resolved
|
||||
root_url = state.INFO.web_url .. "#note_" .. note.id
|
||||
|
||||
-- This appears to be a Gitlab 🐛 where the "type" is returned as an empty string in some cases
|
||||
-- We link these comments to the old file by default
|
||||
if
|
||||
type(note.position) == "table"
|
||||
and note.position.line_range ~= nil
|
||||
and note.position.line_range.start.type == ""
|
||||
then
|
||||
undefined_type = true
|
||||
end
|
||||
range = (type(note.position) == "table" and note.position.line_range or nil)
|
||||
else -- Otherwise insert it as a child node...
|
||||
local note_node = M.build_note(note)
|
||||
table.insert(discussion_children, note_node)
|
||||
@@ -194,6 +186,7 @@ M.add_discussions_to_table = function(items, unlinked)
|
||||
-- Creates the first node in the discussion, and attaches children
|
||||
local body = u.spread(root_text_nodes, discussion_children)
|
||||
local root_node = NuiTree.Node({
|
||||
range = range,
|
||||
text = root_text,
|
||||
type = "note",
|
||||
is_root = true,
|
||||
@@ -204,7 +197,6 @@ M.add_discussions_to_table = function(items, unlinked)
|
||||
old_line = root_old_line,
|
||||
resolvable = resolvable,
|
||||
resolved = resolved,
|
||||
undefined_type = undefined_type,
|
||||
url = root_url,
|
||||
}, body)
|
||||
|
||||
|
||||
@@ -1,28 +1,31 @@
|
||||
local M = {}
|
||||
local state = require("gitlab.state")
|
||||
local List = require("gitlab.utils.list")
|
||||
|
||||
---@param nodes Discussion[]|UnlinkedDiscussion[]|nil
|
||||
---@return number, number
|
||||
local get_data = function(nodes)
|
||||
if nodes == nil then
|
||||
return 0, 0
|
||||
end
|
||||
local total_resolvable = 0
|
||||
local total_resolved = 0
|
||||
if nodes == vim.NIL then
|
||||
return ""
|
||||
if nodes == nil or nodes == vim.NIL then
|
||||
return total_resolvable, total_resolved
|
||||
end
|
||||
|
||||
for _, d in ipairs(nodes) do
|
||||
total_resolvable = List.new(nodes):reduce(function(agg, d)
|
||||
local first_child = d.notes[1]
|
||||
if first_child ~= nil then
|
||||
if first_child.resolvable then
|
||||
total_resolvable = total_resolvable + 1
|
||||
end
|
||||
if first_child.resolved then
|
||||
total_resolved = total_resolved + 1
|
||||
end
|
||||
if first_child and first_child.resolvable then
|
||||
agg = agg + 1
|
||||
end
|
||||
end
|
||||
return agg
|
||||
end, 0)
|
||||
|
||||
total_resolved = List.new(nodes):reduce(function(agg, d)
|
||||
local first_child = d.notes[1]
|
||||
if first_child and first_child.resolved then
|
||||
agg = agg + 1
|
||||
end
|
||||
return agg
|
||||
end, 0)
|
||||
|
||||
return total_resolvable, total_resolved
|
||||
end
|
||||
|
||||
@@ -2,18 +2,19 @@ local M = {}
|
||||
|
||||
local u = require("gitlab.utils")
|
||||
local state = require("gitlab.state")
|
||||
local List = require("gitlab.utils.list")
|
||||
local Popup = require("nui.popup")
|
||||
|
||||
M.open = function()
|
||||
local bufnr = vim.api.nvim_get_current_buf()
|
||||
local keymaps = vim.api.nvim_buf_get_keymap(bufnr, "n")
|
||||
local help_content_lines = {}
|
||||
for _, keymap in ipairs(keymaps) do
|
||||
local help_content_lines = List.new(keymaps):reduce(function(agg, keymap)
|
||||
if keymap.desc ~= nil then
|
||||
local new_line = string.format("%s: %s", keymap.lhs:gsub(" ", "<space>"), keymap.desc)
|
||||
table.insert(help_content_lines, new_line)
|
||||
table.insert(agg, new_line)
|
||||
end
|
||||
end
|
||||
return agg
|
||||
end, {})
|
||||
local longest_line = u.get_longest_string(help_content_lines)
|
||||
local help_popup =
|
||||
Popup(u.create_popup_state("Help", state.settings.popup.help, longest_line + 3, #help_content_lines + 3, 60))
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
local u = require("gitlab.utils")
|
||||
local job = require("gitlab.job")
|
||||
local state = require("gitlab.state")
|
||||
local List = require("gitlab.utils.list")
|
||||
local M = {}
|
||||
|
||||
M.add_label = function()
|
||||
@@ -14,11 +15,9 @@ M.delete_label = function()
|
||||
end
|
||||
|
||||
local refresh_label_state = function(labels)
|
||||
local new_labels = ""
|
||||
for _, label in ipairs(labels) do
|
||||
new_labels = new_labels .. "," .. label
|
||||
end
|
||||
state.INFO.labels = new_labels
|
||||
state.INFO.labels = List.new(labels):reduce(function(agg, label)
|
||||
return agg .. "," .. label
|
||||
end, "")
|
||||
end
|
||||
|
||||
local get_current_labels = function()
|
||||
@@ -31,11 +30,9 @@ local get_current_labels = function()
|
||||
end
|
||||
|
||||
local get_all_labels = function()
|
||||
local labels = {}
|
||||
for _, label in ipairs(state.LABELS) do -- How can we use the colors??
|
||||
table.insert(labels, label.Name)
|
||||
end
|
||||
return labels
|
||||
return List.new(state.LABELS):map(function(label)
|
||||
return label.Name
|
||||
end)
|
||||
end
|
||||
|
||||
M.add_popup = function(type)
|
||||
|
||||
@@ -5,6 +5,7 @@ local Layout = require("nui.layout")
|
||||
local Popup = require("nui.popup")
|
||||
local job = require("gitlab.job")
|
||||
local u = require("gitlab.utils")
|
||||
local List = require("gitlab.utils.list")
|
||||
local state = require("gitlab.state")
|
||||
local miscellaneous = require("gitlab.actions.miscellaneous")
|
||||
local pipeline = require("gitlab.actions.pipeline")
|
||||
@@ -159,8 +160,7 @@ M.build_info_lines = function()
|
||||
return string.rep(" ", offset + 3)
|
||||
end
|
||||
|
||||
local lines = {}
|
||||
for _, v in ipairs(state.settings.info.fields) do
|
||||
return List.new(state.settings.info.fields):map(function(v)
|
||||
if v == "merge_status" then
|
||||
v = "detailed_merge_status"
|
||||
end
|
||||
@@ -174,10 +174,8 @@ M.build_info_lines = function()
|
||||
else
|
||||
line = line .. row.content
|
||||
end
|
||||
table.insert(lines, line)
|
||||
end
|
||||
|
||||
return lines
|
||||
return line
|
||||
end)
|
||||
end
|
||||
|
||||
-- This function will PUT the new description to the Go server
|
||||
|
||||
Reference in New Issue
Block a user