@@ -43,6 +43,58 @@ M.switch_branch = function(branch)
4343 return run_system ({ " git" , " checkout" , " -q" , branch })
4444end
4545
46+ --- Fetches the name of the remote tracking branch for the current branch
47+ --- @return string | nil , string | nil
48+ M .get_remote_branch = function ()
49+ return run_system ({ " git" , " rev-parse" , " --abbrev-ref" , " --symbolic-full-name" , " @{u}" })
50+ end
51+
52+ --- Determines whether the tracking branch is ahead of or behind the current branch, and warns the user if so
53+ --- @param current_branch string
54+ --- @param remote_branch string
55+ --- @param log_level number
56+ --- @return boolean
57+ M .get_ahead_behind = function (current_branch , remote_branch , log_level )
58+ local u = require (" gitlab.utils" )
59+ local result , err =
60+ run_system ({ " git" , " rev-list" , " --left-right" , " --count" , current_branch .. " ..." .. remote_branch })
61+ if err ~= nil or result == nil then
62+ u .notify (" Could not determine if branch is up-to-date: " .. err , vim .log .levels .ERROR )
63+ return false
64+ end
65+
66+ local ahead , behind = result :match (" (%d+)%s+(%d+)" )
67+ if ahead == nil or behind == nil then
68+ u .notify (" Error parsing ahead/behind information." , vim .log .levels .ERROR )
69+ return false
70+ end
71+
72+ ahead = tonumber (ahead )
73+ behind = tonumber (behind )
74+
75+ if ahead > 0 and behind == 0 then
76+ u .notify (string.format (" There are local changes that haven't been pushed to %s yet" , remote_branch ), log_level )
77+ return false
78+ end
79+ if behind > 0 and ahead == 0 then
80+ u .notify (string.format (" There are remote changes on %s that haven't been pulled yet" , remote_branch ), log_level )
81+ return false
82+ end
83+
84+ if ahead > 0 and behind > 0 then
85+ u .notify (
86+ string.format (
87+ " Your branch and the remote %s have diverged. You need to pull, possibly rebase, and then push." ,
88+ remote_branch
89+ ),
90+ log_level
91+ )
92+ return false
93+ end
94+
95+ return true -- Checks passed, branch is up-to-date
96+ end
97+
4698--- Return the name of the current branch
4799--- @return string | nil , string | nil
48100M .get_current_branch = function ()
@@ -93,39 +145,45 @@ M.contains_branch = function(current_branch)
93145 return run_system ({ " git" , " branch" , " -r" , " --contains" , current_branch })
94146end
95147
96- --- Returns true if `branch` is up-to-date on remote, false otherwise.
148+ --- Returns true if `branch` is up-to-date on remote, otherwise false and warns user
97149--- @param log_level integer
98- --- @return boolean | nil
99- M .current_branch_up_to_date_on_remote = function (log_level )
100- local state = require (" gitlab.state" )
101- local current_branch = M .get_current_branch ()
102- local handle = io.popen (" git branch -r --contains " .. current_branch .. " 2>&1" )
103- if not handle then
104- require (" gitlab.utils" ).notify (" Error running 'git branch' command." , vim .log .levels .ERROR )
105- return nil
150+ --- @return boolean
151+ M .check_current_branch_up_to_date_on_remote = function (log_level )
152+ local u = require (" gitlab.utils" )
153+
154+ -- Get current branch
155+ local current_branch , err_current_branch = M .get_current_branch ()
156+ if err_current_branch or not current_branch then
157+ u .notify (" Could not get current branch: " .. err_current_branch , vim .log .levels .ERROR )
158+ return false
106159 end
107160
108- local remote_branches_with_current_head = {}
109- for line in handle :lines () do
110- table.insert (remote_branches_with_current_head , line )
161+ -- Get remote tracking branch
162+ local remote_branch , err_remote_branch = M .get_remote_branch ()
163+ if err_remote_branch or not remote_branch then
164+ u .notify (" Could not get remote branch: " .. err_remote_branch , vim .log .levels .ERROR )
165+ return false
111166 end
112- handle :close ()
113167
114- local current_head_on_remote = List .new (remote_branches_with_current_head ):filter (function (line )
115- return line == string.format (" %s/" , state .settings .connection_settings .remote ) .. current_branch
116- end )
117- local remote_up_to_date = # current_head_on_remote == 1
168+ return M .get_ahead_behind (current_branch , remote_branch , log_level )
169+ end
118170
119- if not remote_up_to_date then
120- require (" gitlab.utils" ).notify (
121- string.format (
122- " You have local commits that are not on %s. Have you forgotten to push?" ,
123- state .settings .connection_settings .remote
124- ),
125- log_level
126- )
171+ --- Warns user if the current MR is in a bad state (closed, has conflicts, merged)
172+ M .check_mr_in_good_condition = function ()
173+ local state = require (" gitlab.state" )
174+ local u = require (" gitlab.utils" )
175+
176+ if state .INFO .has_conflicts then
177+ u .notify (" This merge request has conflicts!" , vim .log .levels .WARN )
178+ end
179+
180+ if state .INFO .state == " closed" then
181+ u .notify (string.format (" This MR was closed %s" , u .time_since (state .INFO .closed_at )), vim .log .levels .WARN )
182+ end
183+
184+ if state .INFO .state == " merged" then
185+ u .notify (string.format (" This MR was merged %s" , u .time_since (state .INFO .merged_at )), vim .log .levels .WARN )
127186 end
128- return remote_up_to_date
129187end
130188
131189return M
0 commit comments