Skip to content

Commit a61cea7

Browse files
ten3robertspritchett
authored andcommitted
feat: merge popup
1 parent 51f00eb commit a61cea7

File tree

12 files changed

+325
-147
lines changed

12 files changed

+325
-147
lines changed

README.md

Lines changed: 65 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ A **work-in-progress** [Magit](https://magit.vc) clone for [Neovim](https://neov
1010
require `nvim-lua/plenary.nvim` using your plugin manager of choice, before requiring this plugin.
1111

1212
| Plugin Manager | Command |
13-
|------------------------------------------------------|--------------------------------------------------------------------------------|
13+
| ---------------------------------------------------- | ------------------------------------------------------------------------------ |
1414
| [Packer](https://github.com/wbthomason/packer.nvim) | `use { 'TimUntersberger/neogit', requires = 'nvim-lua/plenary.nvim' }` |
1515
| [Vim-plug](https://github.com/junegunn/vim-plug) | `Plug 'TimUntersberger/neogit'` |
1616
| [NeoBundle](https://github.com/Shougo/neobundle.vim) | `NeoBundle 'TimUntersberger/neogit'` |
@@ -20,6 +20,7 @@ require `nvim-lua/plenary.nvim` using your plugin manager of choice, before requ
2020
| [Dep](https://github.com/chiyadev/dep) | `{'TimUntersberger/neogit', requires = {'nvim-lua/plenary.nvim'}}` |
2121

2222
You also use in the built-in package manager:
23+
2324
```bash
2425
$ git clone --depth 1 https://github.com/TimUntersberger/neogit $XDG_CONFIG_HOME/nvim/pack/plugins/start/neogit
2526
```
@@ -63,43 +64,44 @@ neogit.open({ cwd = "~" })
6364

6465
The create function takes 1 optional argument that can be one of the following values:
6566

66-
* tab (default)
67-
* replace
68-
* floating (This currently doesn't work with popups. Very unstable)
69-
* split
70-
* split_above
71-
* vsplit
67+
- tab (default)
68+
- replace
69+
- floating (This currently doesn't work with popups. Very unstable)
70+
- split
71+
- split_above
72+
- vsplit
7273

7374
## Status Keybindings
7475

75-
| Keybinding | Function |
76-
|--------------|--------------------------------------------------|
77-
| Tab | Toggle diff |
78-
| 1, 2, 3, 4 | Set a foldlevel |
79-
| $ | Command history |
80-
| b | Branch popup |
81-
| s | Stage (also supports staging selection/hunk) |
82-
| S | Stage unstaged changes |
83-
| \<C-s> | Stage Everything |
84-
| u | Unstage (also supports staging selection/hunk) |
85-
| U | Unstage staged changes |
86-
| c | Open commit popup |
87-
| r | Open rebase popup |
88-
| L | Open log popup |
89-
| p | Open pull popup |
90-
| P | Open push popup |
91-
| Z | Open stash popup |
92-
| ? | Open help popup |
93-
| x | Discard changes (also supports discarding hunks) |
94-
| \<enter> | Go to file |
95-
| \<C-r> | Refresh Buffer |
76+
| Keybinding | Function |
77+
| ---------- | ------------------------------------------------ |
78+
| Tab | Toggle diff |
79+
| 1, 2, 3, 4 | Set a foldlevel |
80+
| $ | Command history |
81+
| b | Branch popup |
82+
| s | Stage (also supports staging selection/hunk) |
83+
| S | Stage unstaged changes |
84+
| \<C-s> | Stage Everything |
85+
| u | Unstage (also supports staging selection/hunk) |
86+
| U | Unstage staged changes |
87+
| c | Open commit popup |
88+
| r | Open rebase popup |
89+
| m | Open merge popup |
90+
| L | Open log popup |
91+
| p | Open pull popup |
92+
| P | Open push popup |
93+
| Z | Open stash popup |
94+
| ? | Open help popup |
95+
| x | Discard changes (also supports discarding hunks) |
96+
| \<enter> | Go to file |
97+
| \<C-r> | Refresh Buffer |
9698

9799
With `diffview` integration enabled
98100

99-
| Keybinding | Function |
100-
|--------------|--------------------------------------------------|
101-
| d | Open `diffview.nvim` at hovered file |
102-
| D (TODO) | Open diff popup |
101+
| Keybinding | Function |
102+
| ---------- | ------------------------------------ |
103+
| d | Open `diffview.nvim` at hovered file |
104+
| D (TODO) | Open diff popup |
103105

104106
## Configuration
105107

@@ -211,29 +213,29 @@ Right now, only the status buffer supports custom mappings.
211213

212214
List of status commands:
213215

214-
* Close
215-
* Depth1 (Set foldlevel to 1)
216-
* Depth2 (Set foldlevel to 2)
217-
* Depth3 (Set foldlevel to 3)
218-
* Depth4 (Set foldlevel to 4)
219-
* Toggle
220-
* Discard (Normal and visual mode)
221-
* Stage (Normal and visual mode)
222-
* StageUnstaged
223-
* StageAll
224-
* GoToFile
225-
* Unstage (Normal and visual mode)
226-
* UnstageStaged
227-
* CommandHistory
228-
* RefreshBuffer
229-
* HelpPopup
230-
* PullPopup
231-
* PushPopup
232-
* FetchPopup
233-
* CommitPopup
234-
* LogPopup
235-
* StashPopup
236-
* BranchPopup
216+
- Close
217+
- Depth1 (Set foldlevel to 1)
218+
- Depth2 (Set foldlevel to 2)
219+
- Depth3 (Set foldlevel to 3)
220+
- Depth4 (Set foldlevel to 4)
221+
- Toggle
222+
- Discard (Normal and visual mode)
223+
- Stage (Normal and visual mode)
224+
- StageUnstaged
225+
- StageAll
226+
- GoToFile
227+
- Unstage (Normal and visual mode)
228+
- UnstageStaged
229+
- CommandHistory
230+
- RefreshBuffer
231+
- HelpPopup
232+
- PullPopup
233+
- PushPopup
234+
- FetchPopup
235+
- CommitPopup
236+
- LogPopup
237+
- StashPopup
238+
- BranchPopup
237239

238240
## Notification Highlighting
239241

@@ -266,6 +268,7 @@ You can override them to fit your colorscheme by creating a `syntax/NeogitStatus
266268
Set `disable_context_highlighting = true` in your call to [`setup`](#configuration) to disable context highlighting altogether.
267269

268270
## Disabling Hint
271+
269272
Set `disable_hint = true` in your call to [`setup`](#configuration) to hide hints on top of the panel.
270273

271274
## Disabling Commit Confirmation
@@ -280,13 +283,13 @@ Set `disable_insert_on_commit = true` in your call to [`setup`](#configuration)
280283

281284
Neogit emits the following events:
282285

283-
| Event | Description |
284-
|-------------------------|----------------------------------|
285-
| `NeogitStatusRefreshed` | Status has been reloaded |
286-
| `NeogitCommitComplete` | Commit has been created |
287-
| `NeogitPushComplete` | Push has completed |
288-
| `NeogitPullComplete` | Pull has completed |
289-
| `NeogitFetchComplete` | Fetch has completed |
286+
| Event | Description |
287+
| ----------------------- | ------------------------ |
288+
| `NeogitStatusRefreshed` | Status has been reloaded |
289+
| `NeogitCommitComplete` | Commit has been created |
290+
| `NeogitPushComplete` | Push has completed |
291+
| `NeogitPullComplete` | Pull has completed |
292+
| `NeogitFetchComplete` | Fetch has completed |
290293

291294
You can listen to the events using the following code:
292295

lua/neogit/buffers/branch_select_view/init.lua

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,10 @@ local M = {}
1010
-- @see Buffer
1111
--
1212
--- Creates a new BranchSelectViewBuffer
13-
-- @param branches
14-
-- @param action
13+
---@param branches string[]
1514
-- @return BranchSelectViewBuffer
16-
function M.new(branches, action)
15+
function M.new(branches)
1716
local instance = {
18-
action = action,
1917
branches = branches,
2018
buffer = nil,
2119
}
@@ -30,7 +28,8 @@ function M:close()
3028
self.buffer = nil
3129
end
3230

33-
function M:open()
31+
---@param action fun(branch: string|nil)
32+
function M:open(action)
3433
self.buffer = Buffer.create {
3534
name = "NeogitBranchSelectView",
3635
filetype = "NeogitBranchSelectView",
@@ -40,9 +39,11 @@ function M:open()
4039
["<enter>"] = function(buffer)
4140
local current_line = buffer:get_current_line()
4241
local branch_name = current_line[1]
43-
if self.action then
44-
self.action(branch_name)
42+
43+
if action then
44+
action(branch_name)
4545
end
46+
4647
self:close()
4748
end,
4849
},
@@ -53,4 +54,9 @@ function M:open()
5354
}
5455
end
5556

57+
local a = require("plenary.async")
58+
59+
---@type fun(self): string|nil
60+
M.open_async = a.wrap(M.open, 2)
61+
5662
return M

lua/neogit/buffers/branch_select_view/ui.lua

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,19 @@ local map = util.map
77

88
local M = {}
99

10+
local function format_branches(list)
11+
local branches = {}
12+
for _, name in ipairs(list) do
13+
local name_formatted = name:match("^remotes/(.*)") or name
14+
if not name_formatted:match("^(.*)/HEAD") then
15+
table.insert(branches, name_formatted)
16+
end
17+
end
18+
return branches
19+
end
20+
1021
function M.View(branches)
11-
return map(branches, function(branch_name)
22+
return map(format_branches(branches), function(branch_name)
1223
return row {
1324
text(branch_name),
1425
}

lua/neogit/config.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ M.values = {
9090
["D"] = "DiffPopup",
9191
["p"] = "PullPopup",
9292
["r"] = "RebasePopup",
93+
["m"] = "MergePopup",
9394
["P"] = "PushPopup",
9495
["c"] = "CommitPopup",
9596
["L"] = "LogPopup",

lua/neogit/lib/git/cli.lua

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,12 @@ local configurations = {
9898
skip = "--skip",
9999
},
100100
},
101+
merge = config {
102+
flags = {
103+
continue = "--continue",
104+
abort = "--abort",
105+
},
106+
},
101107
reset = config {
102108
flags = {
103109
hard = "--hard",

lua/neogit/lib/git/merge.lua

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
local logger = require("neogit.logger")
2+
local client = require("neogit.client")
3+
local notif = require("neogit.lib.notification")
4+
5+
local M = {}
6+
7+
local a = require("plenary.async")
8+
9+
local function merge_command(cmd)
10+
local git = require("neogit.lib.git")
11+
cmd = cmd or git.cli.rebase
12+
local envs = client.get_envs_git_editor()
13+
return cmd.env(envs).show_popup(true):in_pty(true).call(true)
14+
end
15+
16+
function M.rebase_interactive(...)
17+
a.util.scheduler()
18+
local git = require("neogit.lib.git")
19+
local result = merge_command(git.cli.merge.interactive.args(...))
20+
if result.code ~= 0 then
21+
notif.create("Rebasing failed. Resolve conflicts before continuing", vim.log.levels.ERROR)
22+
end
23+
a.util.scheduler()
24+
local status = require("neogit.status")
25+
status.refresh(true, "rebase_interactive")
26+
end
27+
28+
function M.merge(branch, args)
29+
a.util.scheduler()
30+
local git = require("neogit.lib.git")
31+
local result = merge_command(git.cli.merge.args(branch).arg_list(args))
32+
if result.code ~= 0 then
33+
notif.create("Rebasing failed. Resolve conflicts before continuing", vim.log.levels.ERROR)
34+
end
35+
end
36+
37+
function M.continue()
38+
local git = require("neogit.lib.git")
39+
return merge_command(git.cli.merge.continue)
40+
end
41+
42+
function M.abort()
43+
local git = require("neogit.lib.git")
44+
return merge_command(git.cli.merge.abort)
45+
end
46+
47+
local uv = require("neogit.lib.uv")
48+
function M.update_merge_status(state)
49+
local cli = require("neogit.lib.git.cli")
50+
local root = cli.git_root()
51+
if root == "" then
52+
return
53+
end
54+
55+
local merge = {
56+
items = {},
57+
head = nil,
58+
msg = "",
59+
}
60+
61+
local mfile = root .. "/.git/MERGE_HEAD"
62+
local _, stat = a.uv.fs_stat(mfile)
63+
64+
-- Find the rebase progress files
65+
66+
if not stat then
67+
return
68+
end
69+
70+
local err, head = uv.read_file(mfile)
71+
if not head then
72+
logger.error("Failed to read merge head: " .. err)
73+
return
74+
end
75+
head = head:match("([^\r\n]+)")
76+
merge.head = head
77+
78+
local _, msg = uv.read_file(root .. "/.git/MERGE_MSG")
79+
80+
-- we need \r? to support windows
81+
if msg then
82+
merge.msg = msg:match("([^\r\n]+)")
83+
end
84+
85+
state.merge = merge
86+
end
87+
88+
M.register = function(meta)
89+
meta.update_merge_status = M.update_merge_status
90+
end
91+
92+
return M

lua/neogit/lib/git/repository.lua

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ local meta = {
44
__index = {},
55
}
66

7-
local modules = { "status", "diff", "stash", "pull", "push", "log", "rebase" }
7+
local modules = { "status", "diff", "stash", "pull", "push", "log", "rebase", "merge" }
88
for _, m in ipairs(modules) do
99
require("neogit.lib.git." .. m).register(meta.__index)
1010
end
@@ -47,6 +47,11 @@ M.create = function(_path)
4747
items = {},
4848
head = "",
4949
},
50+
merge = {
51+
items = {},
52+
head = nil,
53+
msg = nil,
54+
},
5055
}
5156

5257
return setmetatable(cache, meta)

0 commit comments

Comments
 (0)