Skip to content

Commit 446197d

Browse files
authored
Merge pull request #1580 from NeogitOrg/improve-worktree-support
2 parents d7772bc + 45c0cbb commit 446197d

File tree

21 files changed

+132
-89
lines changed

21 files changed

+132
-89
lines changed

lua/neogit.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ local function construct_opts(opts)
8484

8585
if not opts.cwd then
8686
local git = require("neogit.lib.git")
87-
opts.cwd = git.cli.git_root(".")
87+
opts.cwd = git.cli.worktree_root(".")
8888

8989
if opts.cwd == "" then
9090
opts.cwd = vim.uv.cwd()
@@ -111,7 +111,7 @@ local function open_status_buffer(opts)
111111
-- going to open into. We will use vim.fn.lcd() in the status buffer constructor, so this will eventually be
112112
-- correct.
113113
local repo = require("neogit.lib.git.repository").instance(opts.cwd)
114-
status.new(config.values, repo.git_root, opts.cwd):open(opts.kind):dispatch_refresh()
114+
status.new(config.values, repo.worktree_root, opts.cwd):open(opts.kind):dispatch_refresh()
115115
end
116116

117117
---@alias Popup

lua/neogit/buffers/status/actions.lua

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,7 @@ end
406406
---@param self StatusBuffer
407407
M.v_ignore_popup = function(self)
408408
return popups.open("ignore", function(p)
409-
p { paths = self.buffer.ui:get_filepaths_in_selection(), git_root = git.repo.git_root }
409+
p { paths = self.buffer.ui:get_filepaths_in_selection(), worktree_root = git.repo.worktree_root }
410410
end)
411411
end
412412

@@ -638,7 +638,7 @@ end
638638
---@param _self StatusBuffer
639639
M.n_show_refs = function(_self)
640640
return a.void(function()
641-
require("neogit.buffers.refs_view").new(git.refs.list_parsed(), git.repo.git_root):open()
641+
require("neogit.buffers.refs_view").new(git.refs.list_parsed(), git.repo.worktree_root):open()
642642
end)
643643
end
644644

@@ -1269,7 +1269,7 @@ M.n_ignore_popup = function(self)
12691269
local path = self.buffer.ui:get_hunk_or_filename_under_cursor()
12701270
p {
12711271
paths = { path and path.escaped_path },
1272-
git_root = git.repo.git_root,
1272+
worktree_root = git.repo.worktree_root,
12731273
}
12741274
end)
12751275
end
@@ -1309,7 +1309,7 @@ M.n_help_popup = function(self)
13091309
},
13101310
ignore = {
13111311
paths = { path and path.escaped_path },
1312-
git_root = git.repo.git_root,
1312+
worktree_root = git.repo.worktree_root,
13131313
},
13141314
remote = {},
13151315
fetch = {},
@@ -1364,7 +1364,8 @@ M.n_command = function(self)
13641364
local runner = require("neogit.runner")
13651365

13661366
return a.void(function()
1367-
local cmd = input.get_user_input(("Run command in %s"):format(git.repo.git_root), { prepend = "git " })
1367+
local cmd =
1368+
input.get_user_input(("Run command in %s"):format(git.repo.worktree_root), { prepend = "git " })
13681369
if not cmd then
13691370
return
13701371
end
@@ -1375,7 +1376,7 @@ M.n_command = function(self)
13751376

13761377
local proc = process.new {
13771378
cmd = cmd,
1378-
cwd = git.repo.git_root,
1379+
cwd = git.repo.worktree_root,
13791380
env = {},
13801381
on_error = function()
13811382
return false

lua/neogit/buffers/status/init.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ function M:chdir(dir)
260260
logger.debug("[STATUS] Changing Dir: " .. dir)
261261
vim.api.nvim_set_current_dir(dir)
262262
require("neogit.lib.git.repository").instance(dir)
263-
self.new(config.values, git.repo.git_root, dir):open("replace"):dispatch_refresh()
263+
self.new(config.values, git.repo.worktree_root, dir):open("replace"):dispatch_refresh()
264264
end)
265265
end
266266

lua/neogit/integrations/diffview.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ local function get_local_diff_view(section_name, item_name, opts)
7373
local files = update_files()
7474

7575
local view = CDiffView {
76-
git_root = git.repo.git_root,
76+
git_root = git.repo.worktree_root,
7777
left = left,
7878
right = right,
7979
files = files,

lua/neogit/lib/git/bisect.lua

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ local function bisect(cmd)
1717
end
1818

1919
function M.in_progress()
20-
return git.repo:git_path("BISECT_LOG"):exists()
20+
return git.repo:worktree_git_path("BISECT_LOG"):exists()
2121
end
2222

2323
function M.is_finished()
@@ -74,7 +74,7 @@ M.register = function(meta)
7474

7575
local finished
7676

77-
for line in git.repo:git_path("BISECT_LOG"):iter() do
77+
for line in git.repo:worktree_git_path("BISECT_LOG"):iter() do
7878
if line:match("^#") and line ~= "" then
7979
local action, oid, subject = line:match("^# ([^:]+): %[(.+)%] (.+)")
8080

@@ -96,7 +96,7 @@ M.register = function(meta)
9696
end
9797
end
9898

99-
local expected = vim.trim(git.repo:git_path("BISECT_EXPECTED_REV"):read())
99+
local expected = vim.trim(git.repo:worktree_git_path("BISECT_EXPECTED_REV"):read())
100100
state.bisect.current =
101101
git.log.parse(git.cli.show.format("fuller").args(expected).call({ trim = false }).stdout)[1]
102102

lua/neogit/lib/git/branch.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,7 @@ local function update_branch_information(state)
375375
state.head.oid = status.oid
376376
state.head.detached = status.detached
377377

378-
if status.oid ~= INITIAL_COMMIT then
378+
if status.oid and status.oid ~= INITIAL_COMMIT then
379379
state.head.abbrev = git.rev_parse.abbreviate_commit(status.oid)
380380
state.head.commit_message = git.log.message(status.oid)
381381

lua/neogit/lib/git/cli.lua

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,9 @@ local runner = require("neogit.runner")
368368
---@field verify-commit GitCommandVerifyCommit
369369
---@field worktree GitCommandWorktree
370370
---@field write-tree GitCommandWriteTree
371-
---@field git_root fun(dir: string):string
371+
---@field worktree_root fun(dir: string):string
372+
---@field git_dir fun(dir: string):string
373+
---@field worktree_git_dir fun(dir: string):string
372374
---@field is_inside_worktree fun(dir: string):boolean
373375
---@field history ProcessResult[]
374376

@@ -965,15 +967,34 @@ local configurations = {
965967
["bisect"] = config {},
966968
}
967969

968-
--- NOTE: Use require("neogit.lib.git").repo.git_root instead of calling this function.
969-
--- repository.git_root is used by all other library functions, so it's most likely the one you want to use.
970-
--- git_root_of_cwd() returns the git repo of the cwd, which can change anytime
971-
--- after git_root_of_cwd() has been called.
970+
--- NOTE: Use require("neogit.lib.git").repo.worktree_root instead of calling this function.
971+
--- repository.worktree_root is used by all other library functions, so it's most likely the one you want to use.
972+
--- worktree_root_of_cwd() returns the git repo of the cwd, which can change anytime
973+
--- after worktree_root_of_cwd() has been called.
972974
---@param dir string
973-
---@return string
974-
local function git_root(dir)
975-
local cmd = { "git", "-C", dir, "rev-parse", "--show-toplevel" }
975+
---@return string Absolute path of current worktree
976+
local function worktree_root(dir)
977+
local cmd = { "git", "-C", dir, "rev-parse", "--show-toplevel", "--path-format=absolute" }
976978
local result = vim.system(cmd, { text = true }):wait()
979+
980+
return Path:new(vim.trim(result.stdout)):absolute()
981+
end
982+
983+
---@param dir string
984+
---@return string Absolute path of `.git/` directory
985+
local function git_dir(dir)
986+
local cmd = { "git", "-C", dir, "rev-parse", "--git-common-dir", "--path-format=absolute" }
987+
local result = vim.system(cmd, { text = true }):wait()
988+
989+
return Path:new(vim.trim(result.stdout)):absolute()
990+
end
991+
992+
---@param dir string
993+
---@return string Absolute path of `.git/` directory
994+
local function worktree_git_dir(dir)
995+
local cmd = { "git", "-C", dir, "rev-parse", "--git-dir", "--path-format=absolute" }
996+
local result = vim.system(cmd, { text = true }):wait()
997+
977998
return Path:new(vim.trim(result.stdout)):absolute()
978999
end
9791000

@@ -982,6 +1003,7 @@ end
9821003
local function is_inside_worktree(dir)
9831004
local cmd = { "git", "-C", dir, "rev-parse", "--is-inside-work-tree" }
9841005
local result = vim.system(cmd):wait()
1006+
9851007
return result.code == 0
9861008
end
9871009

@@ -1152,7 +1174,7 @@ local function new_builder(subcommand)
11521174

11531175
return process.new {
11541176
cmd = cmd,
1155-
cwd = git.repo.git_root,
1177+
cwd = git.repo.worktree_root,
11561178
env = state.env,
11571179
input = state.input,
11581180
on_error = opts.on_error,
@@ -1229,7 +1251,9 @@ local meta = {
12291251

12301252
local cli = setmetatable({
12311253
history = runner.history,
1232-
git_root = git_root,
1254+
worktree_root = worktree_root,
1255+
worktree_git_dir = worktree_git_dir,
1256+
git_dir = git_dir,
12331257
is_inside_worktree = is_inside_worktree,
12341258
}, meta)
12351259

lua/neogit/lib/git/hooks.lua

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,13 @@ function M.register(meta)
4747
meta.update_hooks = function(state)
4848
state.hooks = {}
4949

50-
if not Path:new(state.git_root):joinpath(".git", "hooks"):is_dir() then
50+
if not Path:new(state.git_dir):joinpath("hooks"):is_dir() then
5151
return
5252
end
5353

54-
for file in vim.fs.dir(vim.fs.joinpath(state.git_root, ".git", "hooks")) do
54+
for file in vim.fs.dir(vim.fs.joinpath(state.git_dir, "hooks")) do
5555
if not file:match("%.sample$") then
56-
local path = vim.fs.joinpath(state.git_root, ".git", "hooks", file)
56+
local path = vim.fs.joinpath(state.git_dir, "hooks", file)
5757
local stat = vim.uv.fs_stat(path)
5858

5959
if stat and stat.mode and is_executable(stat.mode) then

lua/neogit/lib/git/index.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,10 @@ function M.generate_patch(item, hunk, from, to, reverse)
6767
string.format("@@ -%d,%d +%d,%d @@", hunk.index_from, len_start, hunk.index_from, len_start + len_offset)
6868
)
6969

70-
local git_root = git.repo.git_root
70+
local worktree_root = git.repo.worktree_root
7171

7272
assert(item.absolute_path, "Item is not a path")
73-
local path = Path:new(item.absolute_path):make_relative(git_root)
73+
local path = Path:new(item.absolute_path):make_relative(worktree_root)
7474

7575
table.insert(diff_content, 1, string.format("+++ b/%s", path))
7676
table.insert(diff_content, 1, string.format("--- a/%s", path))

lua/neogit/lib/git/merge.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,15 @@ M.register = function(meta)
4444
meta.update_merge_status = function(state)
4545
state.merge = { head = nil, branch = nil, msg = "", items = {} }
4646

47-
local merge_head = git.repo:git_path("MERGE_HEAD")
47+
local merge_head = git.repo:worktree_git_path("MERGE_HEAD")
4848
if not merge_head:exists() then
4949
return
5050
end
5151

5252
state.merge.head = merge_head:read():match("([^\r\n]+)")
5353
state.merge.subject = git.log.message(state.merge.head)
5454

55-
local message = git.repo:git_path("MERGE_MSG")
55+
local message = git.repo:worktree_git_path("MERGE_MSG")
5656
if message:exists() then
5757
state.merge.msg = message:read():match("([^\r\n]+)") -- we need \r? to support windows
5858
state.merge.branch = state.merge.msg:match("Merge branch '(.*)'$")

0 commit comments

Comments
 (0)