Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions lua/gitlab/actions/comment.lua
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,10 @@ M.can_create_comment = function(must_be_visual)
return false
end

if not git.check_current_branch_up_to_date_on_remote(vim.log.levels.ERROR) then
return false
end

-- Check we're in visual mode for code suggestions and multiline comments
if must_be_visual and not u.check_visual_mode() then
return false
Expand Down
3 changes: 3 additions & 0 deletions lua/gitlab/actions/discussions/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ end
---Makes API call to get the discussion data, stores it in the state, and calls the callback
---@param callback function|nil
M.load_discussions = function(callback)
local git = require("gitlab.git")
local ahead, behind = git.get_ahead_behind(git.get_current_branch(), git.get_remote_branch())
state.ahead_behind = { ahead, behind }
state.discussion_tree.last_updated = nil
state.load_new_state("discussion_data", function(data)
if not state.DISCUSSION_DATA then
Expand Down
19 changes: 17 additions & 2 deletions lua/gitlab/actions/discussions/winbar.lua
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ local function content()
resolved_notes = resolved_notes,
non_resolvable_notes = non_resolvable_notes,
help_keymap = state.settings.keymaps.help,
ahead = state.ahead_behind[1],
behind = state.ahead_behind[2],
updated = updated,
}

Expand Down Expand Up @@ -158,7 +160,7 @@ end
M.make_winbar = function(t)
local discussions_focused = M.current_view_type == "discussions"
local discussion_text = add_drafts_and_resolvable(
"Inline Comments:",
"Comments:",
t.resolvable_discussions,
t.resolved_discussions,
t.inline_draft_notes,
Expand Down Expand Up @@ -190,15 +192,18 @@ M.make_winbar = function(t)
local separator = "%#Comment#|"
local end_section = "%="
local updated = "%#Text#" .. t.updated
local ahead_behind = M.get_ahead_behind(t.ahead, t.behind)
local help = "%#Comment#Help: " .. (t.help_keymap and t.help_keymap:gsub(" ", "<space>") .. " " or "unmapped")
return string.format(
" %s %s %s %s %s %s %s %s %s %s %s",
" %s %s %s %s %s %s %s %s %s %s %s %s %s",
discussion_text,
separator,
notes_text,
end_section,
updated,
separator,
ahead_behind,
separator,
sort_method,
separator,
mode,
Expand Down Expand Up @@ -254,6 +259,16 @@ M.get_mode = function()
end
end

---@param ahead number|nil
---@param behind number|nil
M.get_ahead_behind = function(ahead, behind)
local a = ahead == nil and "?" or tostring(ahead)
local b = behind == nil and "?" or tostring(behind)
a = ((a == "?" or a == "0") and "%#Comment#" or "%#WarningMsg#") .. a
b = ((b == "?" or b == "0") and "%#Comment#" or "%#WarningMsg#") .. b
return a .. "↑ " .. b .. "↓"
end

---Toggles the current view type (or sets it to `override`) and then updates the view.
---@param override "discussions"|"notes" Defines the view type to select.
M.switch_view_type = function(override)
Expand Down
2 changes: 2 additions & 0 deletions lua/gitlab/annotations.lua
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@
---@field resolved_notes number
---@field non_resolvable_notes number
---@field help_keymap string
---@field ahead number|nil -- Number of commits local is ahead of remote
---@field behind number|nil -- Number of commits local is behind remote
---@field updated string
---
---@class SignTable
Expand Down
75 changes: 37 additions & 38 deletions lua/gitlab/git.lua
Original file line number Diff line number Diff line change
Expand Up @@ -74,54 +74,34 @@ M.fetch_remote_branch = function(remote_branch)
return true
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)
---Determines whether the tracking branch is ahead of or behind the current branch and returns the
---number of ahead and behind commits or nil values in case of errors.
---@param current_branch string|nil
---@param remote_branch string|nil
---@return integer|nil ahead, integer|nil behind
M.get_ahead_behind = function(current_branch, remote_branch)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is refactored to only get the number of commits and not show warnings to the user so that it can be used more often without annoying the user. The notification is moved up to the check_current_branch_up_to_date_on_remote function.

if current_branch == nil or remote_branch == nil then
return nil, nil
end
if not M.fetch_remote_branch(remote_branch) then
return false
return nil, nil
end

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
return nil, nil
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
u.notify("Error parsing ahead/behind information", vim.log.levels.ERROR)
return nil, nil
end

return true -- Checks passed, branch is up-to-date
return tonumber(ahead), tonumber(behind)
end

---Return the name of the current branch or nil if it can't be retrieved
Expand Down Expand Up @@ -184,16 +164,35 @@ end
---@return boolean
M.check_current_branch_up_to_date_on_remote = function(log_level)
local current_branch = M.get_current_branch()
if current_branch == nil then
local remote_branch = M.get_remote_branch()
local ahead, behind = M.get_ahead_behind(current_branch, remote_branch)
if ahead == nil or behind == nil then
return false
end

local remote_branch = M.get_remote_branch()
if remote_branch == nil then
local u = require("gitlab.utils")

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

return M.get_ahead_behind(current_branch, remote_branch, log_level)
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

---Warns user if the current MR is in a bad state (closed, has conflicts, merged)
Expand Down
9 changes: 5 additions & 4 deletions lua/gitlab/state.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@
-- This module is also responsible for ensuring that the state of the plugin
-- is valid via dependencies

local git = require("gitlab.git")
local u = require("gitlab.utils")
local List = require("gitlab.utils.list")
local M = {}

M.emoji_map = nil
local M = {
emoji_map = nil,
ahead_behind = { nil, nil },
}

---Returns a gitlab token, and a gitlab URL. Used to connect to gitlab.
---@return string|nil, string|nil, string|nil
M.default_auth_provider = function()
local git = require("gitlab.git")
local base_path, err = M.settings.config_path, nil
if base_path == nil then
base_path, err = git.base_dir()
Expand Down
Loading