Skip to content
Merged
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: 2 additions & 2 deletions lua/neogit.lua
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ local function construct_opts(opts)

if not opts.cwd then
local git = require("neogit.lib.git")
opts.cwd = git.cli.git_root(".")
opts.cwd = git.cli.worktree_root(".")

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

---@alias Popup
Expand Down
13 changes: 7 additions & 6 deletions lua/neogit/buffers/status/actions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@ end
---@param self StatusBuffer
M.v_ignore_popup = function(self)
return popups.open("ignore", function(p)
p { paths = self.buffer.ui:get_filepaths_in_selection(), git_root = git.repo.git_root }
p { paths = self.buffer.ui:get_filepaths_in_selection(), worktree_root = git.repo.worktree_root }
end)
end

Expand Down Expand Up @@ -638,7 +638,7 @@ end
---@param _self StatusBuffer
M.n_show_refs = function(_self)
return a.void(function()
require("neogit.buffers.refs_view").new(git.refs.list_parsed(), git.repo.git_root):open()
require("neogit.buffers.refs_view").new(git.refs.list_parsed(), git.repo.worktree_root):open()
end)
end

Expand Down Expand Up @@ -1269,7 +1269,7 @@ M.n_ignore_popup = function(self)
local path = self.buffer.ui:get_hunk_or_filename_under_cursor()
p {
paths = { path and path.escaped_path },
git_root = git.repo.git_root,
worktree_root = git.repo.worktree_root,
}
end)
end
Expand Down Expand Up @@ -1309,7 +1309,7 @@ M.n_help_popup = function(self)
},
ignore = {
paths = { path and path.escaped_path },
git_root = git.repo.git_root,
worktree_root = git.repo.worktree_root,
},
remote = {},
fetch = {},
Expand Down Expand Up @@ -1364,7 +1364,8 @@ M.n_command = function(self)
local runner = require("neogit.runner")

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

local proc = process.new {
cmd = cmd,
cwd = git.repo.git_root,
cwd = git.repo.worktree_root,
env = {},
on_error = function()
return false
Expand Down
2 changes: 1 addition & 1 deletion lua/neogit/buffers/status/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ function M:chdir(dir)
logger.debug("[STATUS] Changing Dir: " .. dir)
vim.api.nvim_set_current_dir(dir)
require("neogit.lib.git.repository").instance(dir)
self.new(config.values, git.repo.git_root, dir):open("replace"):dispatch_refresh()
self.new(config.values, git.repo.worktree_root, dir):open("replace"):dispatch_refresh()
end)
end

Expand Down
2 changes: 1 addition & 1 deletion lua/neogit/integrations/diffview.lua
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ local function get_local_diff_view(section_name, item_name, opts)
local files = update_files()

local view = CDiffView {
git_root = git.repo.git_root,
git_root = git.repo.worktree_root,
left = left,
right = right,
files = files,
Expand Down
6 changes: 3 additions & 3 deletions lua/neogit/lib/git/bisect.lua
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ local function bisect(cmd)
end

function M.in_progress()
return git.repo:git_path("BISECT_LOG"):exists()
return git.repo:worktree_git_path("BISECT_LOG"):exists()
end

function M.is_finished()
Expand Down Expand Up @@ -74,7 +74,7 @@ M.register = function(meta)

local finished

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

Expand All @@ -96,7 +96,7 @@ M.register = function(meta)
end
end

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

Expand Down
2 changes: 1 addition & 1 deletion lua/neogit/lib/git/branch.lua
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ local function update_branch_information(state)
state.head.oid = status.oid
state.head.detached = status.detached

if status.oid ~= INITIAL_COMMIT then
if status.oid and status.oid ~= INITIAL_COMMIT then
state.head.abbrev = git.rev_parse.abbreviate_commit(status.oid)
state.head.commit_message = git.log.message(status.oid)

Expand Down
44 changes: 34 additions & 10 deletions lua/neogit/lib/git/cli.lua
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,9 @@ local runner = require("neogit.runner")
---@field verify-commit GitCommandVerifyCommit
---@field worktree GitCommandWorktree
---@field write-tree GitCommandWriteTree
---@field git_root fun(dir: string):string
---@field worktree_root fun(dir: string):string
---@field git_dir fun(dir: string):string
---@field worktree_git_dir fun(dir: string):string
---@field is_inside_worktree fun(dir: string):boolean
---@field history ProcessResult[]

Expand Down Expand Up @@ -965,15 +967,34 @@ local configurations = {
["bisect"] = config {},
}

--- NOTE: Use require("neogit.lib.git").repo.git_root instead of calling this function.
--- repository.git_root is used by all other library functions, so it's most likely the one you want to use.
--- git_root_of_cwd() returns the git repo of the cwd, which can change anytime
--- after git_root_of_cwd() has been called.
--- NOTE: Use require("neogit.lib.git").repo.worktree_root instead of calling this function.
--- repository.worktree_root is used by all other library functions, so it's most likely the one you want to use.
--- worktree_root_of_cwd() returns the git repo of the cwd, which can change anytime
--- after worktree_root_of_cwd() has been called.
---@param dir string
---@return string
local function git_root(dir)
local cmd = { "git", "-C", dir, "rev-parse", "--show-toplevel" }
---@return string Absolute path of current worktree
local function worktree_root(dir)
local cmd = { "git", "-C", dir, "rev-parse", "--show-toplevel", "--path-format=absolute" }
local result = vim.system(cmd, { text = true }):wait()

return Path:new(vim.trim(result.stdout)):absolute()
end

---@param dir string
---@return string Absolute path of `.git/` directory
local function git_dir(dir)
local cmd = { "git", "-C", dir, "rev-parse", "--git-common-dir", "--path-format=absolute" }
local result = vim.system(cmd, { text = true }):wait()

return Path:new(vim.trim(result.stdout)):absolute()
end

---@param dir string
---@return string Absolute path of `.git/` directory
local function worktree_git_dir(dir)
local cmd = { "git", "-C", dir, "rev-parse", "--git-dir", "--path-format=absolute" }
local result = vim.system(cmd, { text = true }):wait()

return Path:new(vim.trim(result.stdout)):absolute()
end

Expand All @@ -982,6 +1003,7 @@ end
local function is_inside_worktree(dir)
local cmd = { "git", "-C", dir, "rev-parse", "--is-inside-work-tree" }
local result = vim.system(cmd):wait()

return result.code == 0
end

Expand Down Expand Up @@ -1152,7 +1174,7 @@ local function new_builder(subcommand)

return process.new {
cmd = cmd,
cwd = git.repo.git_root,
cwd = git.repo.worktree_root,
env = state.env,
input = state.input,
on_error = opts.on_error,
Expand Down Expand Up @@ -1229,7 +1251,9 @@ local meta = {

local cli = setmetatable({
history = runner.history,
git_root = git_root,
worktree_root = worktree_root,
worktree_git_dir = worktree_git_dir,
git_dir = git_dir,
is_inside_worktree = is_inside_worktree,
}, meta)

Expand Down
6 changes: 3 additions & 3 deletions lua/neogit/lib/git/hooks.lua
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,13 @@ function M.register(meta)
meta.update_hooks = function(state)
state.hooks = {}

if not Path:new(state.git_root):joinpath(".git", "hooks"):is_dir() then
if not Path:new(state.git_dir):joinpath("hooks"):is_dir() then
return
end

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

if stat and stat.mode and is_executable(stat.mode) then
Expand Down
4 changes: 2 additions & 2 deletions lua/neogit/lib/git/index.lua
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,10 @@ function M.generate_patch(item, hunk, from, to, reverse)
string.format("@@ -%d,%d +%d,%d @@", hunk.index_from, len_start, hunk.index_from, len_start + len_offset)
)

local git_root = git.repo.git_root
local worktree_root = git.repo.worktree_root

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

table.insert(diff_content, 1, string.format("+++ b/%s", path))
table.insert(diff_content, 1, string.format("--- a/%s", path))
Expand Down
4 changes: 2 additions & 2 deletions lua/neogit/lib/git/merge.lua
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,15 @@ M.register = function(meta)
meta.update_merge_status = function(state)
state.merge = { head = nil, branch = nil, msg = "", items = {} }

local merge_head = git.repo:git_path("MERGE_HEAD")
local merge_head = git.repo:worktree_git_path("MERGE_HEAD")
if not merge_head:exists() then
return
end

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

local message = git.repo:git_path("MERGE_MSG")
local message = git.repo:worktree_git_path("MERGE_MSG")
if message:exists() then
state.merge.msg = message:read():match("([^\r\n]+)") -- we need \r? to support windows
state.merge.branch = state.merge.msg:match("Merge branch '(.*)'$")
Expand Down
4 changes: 2 additions & 2 deletions lua/neogit/lib/git/rebase.lua
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,8 @@ function M.update_rebase_status(state)
state.rebase = { items = {}, onto = {}, head_oid = nil, head = nil, current = nil }

local rebase_file
local rebase_merge = git.repo:git_path("rebase-merge")
local rebase_apply = git.repo:git_path("rebase-apply")
local rebase_merge = git.repo:worktree_git_path("rebase-merge")
local rebase_apply = git.repo:worktree_git_path("rebase-apply")

if rebase_merge:exists() then
rebase_file = rebase_merge
Expand Down
2 changes: 1 addition & 1 deletion lua/neogit/lib/git/refs.lua
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ M.heads = util.memoize(function()
local heads = { "HEAD", "ORIG_HEAD", "FETCH_HEAD", "MERGE_HEAD", "CHERRY_PICK_HEAD" }
local present = {}
for _, head in ipairs(heads) do
if git.repo:git_path(head):exists() then
if git.repo:worktree_git_path(head):exists() then
table.insert(present, head)
end
end
Expand Down
71 changes: 44 additions & 27 deletions lua/neogit/lib/git/repository.lua
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,25 @@ local modules = {
}

---@class NeogitRepoState
---@field git_path fun(self, ...): Path
---@field refresh fun(self, table)
---@field git_root string
---@field head NeogitRepoHead
---@field upstream NeogitRepoRemote
---@field pushRemote NeogitRepoRemote
---@field untracked NeogitRepoIndex
---@field unstaged NeogitRepoIndex
---@field staged NeogitRepoIndex
---@field stashes NeogitRepoStash
---@field recent NeogitRepoRecent
---@field sequencer NeogitRepoSequencer
---@field rebase NeogitRepoRebase
---@field merge NeogitRepoMerge
---@field bisect NeogitRepoBisect
---@field hooks string[]
---@field git_path fun(self, ...): Path
---@field worktree_git_path fun(self, ...): Path
---@field refresh fun(self, table)
---@field worktree_root string Absolute path to the root of the current worktree
---@field worktree_git_dir string Absolute path to the .git/ dir of the current worktree
---@field git_dir string Absolute path of the .git/ dir for the repository
---@field head NeogitRepoHead
---@field upstream NeogitRepoRemote
---@field pushRemote NeogitRepoRemote
---@field untracked NeogitRepoIndex
---@field unstaged NeogitRepoIndex
---@field staged NeogitRepoIndex
---@field stashes NeogitRepoStash
---@field recent NeogitRepoRecent
---@field sequencer NeogitRepoSequencer
---@field rebase NeogitRepoRebase
---@field merge NeogitRepoMerge
---@field bisect NeogitRepoBisect
---@field hooks string[]
---
---@class NeogitRepoHead
---@field branch string|nil
Expand Down Expand Up @@ -98,7 +101,9 @@ local modules = {
---@return NeogitRepoState
local function empty_state()
return {
git_root = "",
worktree_root = "",
worktree_git_dir = "",
git_dir = "",
head = {
branch = nil,
detached = false,
Expand Down Expand Up @@ -165,12 +170,14 @@ local function empty_state()
end

---@class NeogitRepo
---@field lib table
---@field state NeogitRepoState
---@field git_root string
---@field running table
---@field interrupt table
---@field tmp_state table
---@field lib table
---@field state NeogitRepoState
---@field worktree_root string Project root, or worktree
---@field worktree_git_dir string Dir to watch for changes in worktree
---@field git_dir string '.git/' directory for repo
---@field running table
---@field interrupt table
---@field tmp_state table
---@field refresh_callbacks function[]
local Repo = {}
Repo.__index = Repo
Expand Down Expand Up @@ -205,14 +212,18 @@ function Repo.new(dir)
local instance = {
lib = {},
state = empty_state(),
git_root = git.cli.git_root(dir),
worktree_root = git.cli.worktree_root(dir),
worktree_git_dir = git.cli.worktree_git_dir(dir),
git_dir = git.cli.git_dir(dir),
refresh_callbacks = {},
running = util.weak_table(),
interrupt = util.weak_table(),
tmp_state = util.weak_table("v"),
}

instance.state.git_root = instance.git_root
instance.state.worktree_root = instance.worktree_root
instance.state.worktree_git_dir = instance.worktree_git_dir
instance.state.git_dir = instance.git_dir

setmetatable(instance, Repo)

Expand All @@ -227,8 +238,14 @@ function Repo:reset()
self.state = empty_state()
end

---@return Path
function Repo:worktree_git_path(...)
return Path:new(self.worktree_git_dir):joinpath(...)
end

---@return Path
function Repo:git_path(...)
return Path:new(self.git_root):joinpath(".git", ...)
return Path:new(self.git_dir):joinpath(...)
end

function Repo:tasks(filter, state)
Expand Down Expand Up @@ -277,7 +294,7 @@ function Repo:set_state(id)
end

function Repo:refresh(opts)
if self.git_root == "" then
if self.worktree_root == "" then
logger.debug("[REPO] No git root found - skipping refresh")
return
end
Expand Down
Loading
Loading