Repository navigation
Expand file tree
/
Copy pathrebase.lua
More file actions
108 lines (91 loc) · 3.4 KB
/
Copy pathrebase.lua
File metadata and controls
108 lines (91 loc) · 3.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
-- This module is responsible for rebasing the MR on the Gitlab server and updating the local
-- branch and reviewer state.
local M = {}
---@class RebaseOpts Overrides for the rebase function.
---@field skip_ci? boolean If true, a CI pipeline is not created
---@field force? boolean If true, MR is rebased even if MR already is rebased. This is a client-side concept (not sent to Go server)
---Return true if the rebase is possible, otherwise false.
---@param opts RebaseOpts
---@return boolean
local can_rebase = function(opts)
local u = require("gitlab.utils")
-- Check if there are local changes (we wouldn't be able to run `git pull` after rebasing)
local has_clean_tree, err = require("gitlab.git").has_clean_tree()
if not has_clean_tree then
u.notify("Cannot rebase when there are changed files", vim.log.levels.ERROR)
return false
elseif err ~= nil then
u.notify("Error while inspecting working tree", vim.log.levels.ERROR)
return false
end
local state = require("gitlab.state")
local already_rebased = vim.iter(state.MERGEABILITY):find(function(check)
return check.identifier == "NEED_REBASE" and check.status == "SUCCESS"
end)
local force = require("gitlab.state").settings.rebase_mr.force
if opts.force ~= nil then
force = opts.force
end
if already_rebased and not force then
u.notify("MR is already rebased", vim.log.levels.ERROR)
return false
end
local has_conflicts = vim.iter(state.MERGEABILITY):find(function(check)
return check.identifier == "CONFLICT" and check.status ~= "SUCCESS" and check.status ~= "INACTIVE"
end)
if has_conflicts then
if has_conflicts.status == "FAILED" then
u.notify("Rebase locally, resolve all conflicts, then push the branch", vim.log.levels.ERROR)
else
u.notify("Check for conflicts hasn't passed successfully", vim.log.levels.WARN)
end
return false
end
return true
end
---Callback to run after the async `git pull` call exits.
---@param result? string The stdout from the `git pull` call if any
---@param err? string The stderr from the `git pull` call if any
local on_pull_exit = function(result, err)
if result ~= nil then
local reviewer = require("gitlab.reviewer")
if reviewer.tabid ~= nil then
reviewer.reload()
end
elseif err ~= nil then
require("gitlab.utils").notify(err, vim.log.levels.ERROR)
end
end
---@class RebaseBody
---@field skip_ci boolean? If true, a CI pipeline is not created.
---Send request to Go server to rebase MR.
---@param rebase_body RebaseBody
local confirm_rebase = function(rebase_body)
local u = require("gitlab.utils")
u.notify("Rebase in progress", vim.log.levels.INFO)
local client = require("gitlab.client")
client.send_request("/mr/rebase", "POST", rebase_body, function(data)
u.notify(data.message .. ", updating local state", vim.log.levels.INFO)
local state = require("gitlab.state")
require("gitlab.git_async").pull(
state.settings.connection_settings.remote,
state.INFO.source_branch,
on_pull_exit,
{ "--rebase" }
)
end)
end
---Rebase the feature branch on the server.
---@param opts RebaseOpts
M.rebase = function(opts)
opts = opts or {}
if not can_rebase(opts) then
return
end
local rebase_body = { skip_ci = require("gitlab.state").settings.rebase_mr.skip_ci }
if opts.skip_ci ~= nil then
rebase_body.skip_ci = opts.skip_ci
end
confirm_rebase(rebase_body)
end
return M