Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show all untracked files instead of just the directory #722

Merged
merged 11 commits into from
Aug 9, 2023
2 changes: 1 addition & 1 deletion lua/neogit/lib/git/branch.lua
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ function M.pushRemote_ref(branch)
local pushRemote = M.pushRemote(branch)

if branch and pushRemote then
return pushRemote .. "/" .. branch
return string.format("%s/%s", pushRemote, branch)
end
end

Expand Down
24 changes: 12 additions & 12 deletions lua/neogit/lib/git/diff.lua
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ local function build_metatable(f, raw_output_fn)
if method == "diff" then
self.diff = a.util.block_on(function()
logger.debug("[DIFF] Loading diff for: " .. f.name)
return parse_diff(raw_output_fn())
return parse_diff(unpack(raw_output_fn()))
end)

return self.diff
Expand All @@ -193,7 +193,11 @@ end
-- Doing a git-diff with untracked files will exit(1) if a difference is observed, which we can ignore.
local function raw_untracked(name)
return function()
return cli.diff.no_ext_diff.no_index.files("/dev/null", name).call_ignoring_exit_code():trim().stdout, {}
local diff =
cli.diff.no_ext_diff.no_index.files("/dev/null", name).call_ignoring_exit_code():trim().stdout
local stats = {}

return { diff, stats }
end
end

Expand All @@ -202,7 +206,7 @@ local function raw_unstaged(name)
local diff = cli.diff.no_ext_diff.files(name).call():trim().stdout
local stats = cli.diff.no_ext_diff.shortstat.files(name).call():trim().stdout

return diff, stats
return { diff, stats }
end
end

Expand All @@ -211,7 +215,7 @@ local function raw_staged(name)
local diff = cli.diff.no_ext_diff.cached.files(name).call():trim().stdout
local stats = cli.diff.no_ext_diff.cached.shortstat.files(name).call():trim().stdout

return diff, stats
return { diff, stats }
end
end

Expand All @@ -237,17 +241,13 @@ return {
end

for _, f in ipairs(repo.unstaged.items) do
if f.mode ~= "F" then
invalidate_diff(filter, "unstaged", f)
build_metatable(f, raw_unstaged(f.name))
end
invalidate_diff(filter, "unstaged", f)
build_metatable(f, raw_unstaged(f.name))
end

for _, f in ipairs(repo.staged.items) do
if f.mode ~= "F" then
invalidate_diff(filter, "staged", f)
build_metatable(f, raw_staged(f.name))
end
invalidate_diff(filter, "staged", f)
build_metatable(f, raw_staged(f.name))
end
end
end,
Expand Down
18 changes: 9 additions & 9 deletions lua/neogit/lib/git/pull.lua
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
local cli = require("neogit.lib.git.cli")
local util = require("neogit.lib.util")

local M = {}

Expand All @@ -10,23 +9,24 @@ function M.pull_interactive(remote, branch, args)
end

local function update_unpulled(state)
state.upstream.unpulled.items = {}
state.pushRemote.unpulled.items = {}

if state.upstream.ref then
local result = cli.log.oneline.for_range("..@{upstream}").show_popup(false).call():trim().stdout

state.upstream.unpulled = { items = {} }
state.upstream.unpulled.items = util.map(result, function(x)
return { name = x }
end)
for _, name in ipairs(result) do
table.insert(state.upstream.unpulled.items, { name = name })
end
end

local pushRemote = require("neogit.lib.git").branch.pushRemote_ref()
if pushRemote then
local result = cli.log.oneline.for_range(".." .. pushRemote).show_popup(false).call():trim().stdout

state.pushRemote.unpulled = { items = {} }
state.pushRemote.unpulled.items = util.map(result, function(x)
return { name = x }
end)
for _, name in ipairs(result) do
table.insert(state.pushRemote.unpulled.items, { name = name })
end
end
end

Expand Down
5 changes: 3 additions & 2 deletions lua/neogit/lib/git/push.lua
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ function M.push_interactive(remote, branch, args)
end

local function update_unmerged(state)
state.upstream.unmerged.items = {}
state.pushRemote.unmerged.items = {}

if state.upstream.ref then
state.upstream.unmerged = { items = {} }
state.upstream.unmerged.items = util.filter_map(log.list { "@{upstream}.." }, function(v)
if v.oid then
return {
Expand All @@ -29,7 +31,6 @@ local function update_unmerged(state)

local pushRemote = require("neogit.lib.git").branch.pushRemote_ref()
if pushRemote then
state.pushRemote.unmerged = { items = {} }
state.pushRemote.unmerged.items = util.filter_map(log.list { pushRemote .. ".." }, function(v)
if v.oid then
return {
Expand Down
9 changes: 6 additions & 3 deletions lua/neogit/lib/git/repository.lua
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,20 @@ local function empty_state()
end,
cwd = vim.fn.getcwd(),
git_root = root,
head = { branch = nil, commit_message = "" },
head = {
branch = nil,
commit_message = nil
},
upstream = {
branch = nil,
commit_message = "",
commit_message = nil,
remote = nil,
ref = nil,
unmerged = { items = {} },
unpulled = { items = {} },
},
pushRemote = {
commit_message = "",
commit_message = nil,
unmerged = { items = {} },
unpulled = { items = {} },
},
Expand Down
83 changes: 56 additions & 27 deletions lua/neogit/lib/git/status.lua
Original file line number Diff line number Diff line change
Expand Up @@ -28,45 +28,51 @@ local function update_status(state)
local cwd = vim.fn.getcwd()
local result = git.cli.status.porcelain(2).branch.call():trim()

local head = {}
local upstream = { unmerged = { items = {} }, unpulled = { items = {} } }

local untracked_files, unstaged_files, staged_files = {}, {}, {}
local old_files_hash = {
staged_files = Collection.new(state.staged.items or {}):key_by("name"),
unstaged_files = Collection.new(state.unstaged.items or {}):key_by("name"),
untracked_files = Collection.new(state.untracked.items or {}):key_by("name"),
}

local match_kind = "(.) (.+)"
local match_u = "(..) (....) (%d+) (%d+) (%d+) (%d+) (%w+) (%w+) (%w+) (.+)"
local match_1 = "(.)(.) (....) (%d+) (%d+) (%d+) (%w+) (%w+) (.+)"
local match_2 = "(.)(.) (....) (%d+) (%d+) (%d+) (%w+) (%w+) (%a%d+) ([^\t]+)\t?(.+)"

for _, l in ipairs(result.stdout) do
local header, value = l:match("# ([%w%.]+) (.+)")
if header then
if header == "branch.head" then
state.head.branch = value
head.branch = value
elseif header == "branch.oid" then
state.head.oid = value
head.oid = value
elseif header == "branch.upstream" then
state.upstream.ref = value
upstream.ref = value

local remote, branch = unpack(vim.split(value, "/"))
state.upstream.remote = remote
state.upstream.branch = branch
upstream.remote = remote
upstream.branch = branch
end
else
local kind, rest = l:match("(.) (.+)")
if kind == "?" then
table.insert(untracked_files, {
name = rest,
})
elseif kind == "u" then
local mode, _, _, _, _, _, _, _, _, name =
rest:match("(..) (....) (%d+) (%d+) (%d+) (%d+) (%w+) (%w+) (%w+) (.+)")
table.insert(untracked_files, {
mode = mode,
name = name,
})
-- selene: allow(empty_if)
elseif kind == "!" then
-- we ignore ignored files for now
local kind, rest = l:match(match_kind)

-- kinds:
-- u = Unmerged
-- 1 = Ordinary Entries
-- 2 = Renamed/Copied Entries
-- ? = Untracked
-- ! = Ignored

if kind == "u" then
local mode, _, _, _, _, _, _, _, _, name = rest:match(match_u)

table.insert(untracked_files, { mode = mode, name = name })
elseif kind == "1" then
local mode_staged, mode_unstaged, _, _, _, _, _, _, name =
rest:match("(.)(.) (....) (%d+) (%d+) (%d+) (%w+) (%w+) (.+)")
local mode_staged, mode_unstaged, _, _, _, _, _, _, name = rest:match(match_1)

if mode_staged ~= "." then
table.insert(staged_files, update_file(old_files_hash.staged_files[name], mode_staged, name))
Expand All @@ -76,11 +82,9 @@ local function update_status(state)
table.insert(unstaged_files, update_file(old_files_hash.unstaged_files[name], mode_unstaged, name))
end
elseif kind == "2" then
local mode_staged, mode_unstaged, _, _, _, _, _, _, _, name, orig_name =
rest:match("(.)(.) (....) (%d+) (%d+) (%d+) (%w+) (%w+) (%a%d+) ([^\t]+)\t?(.+)")
local entry = {
name = name,
}
local mode_staged, mode_unstaged, _, _, _, _, _, _, _, name, orig_name = rest:match(match_2)

local entry = { name = name }

if mode_staged ~= "." then
entry.mode = mode_staged
Expand All @@ -99,7 +103,32 @@ local function update_status(state)
end
end

local untracked = git.cli["ls-files"].others.exclude_standard.args(".").call():trim().stdout
for _, name in ipairs(untracked) do
table.insert(untracked_files, update_file(old_files_hash.untracked_files[name], nil, name))
end

-- These are a bit hacky - because we can _partially_ refresh repo state (for now),
-- some things need to be carried over here.
if not state.head.branch or head.branch == state.head.branch then
head.commit_message = state.head.commit_message
end

if not upstream.ref or upstream.ref == state.upstream.ref then
upstream.commit_message = state.upstream.commit_message
end

if #state.upstream.unmerged.items > 0 then
upstream.unmerged = state.upstream.unmerged
end

if #state.upstream.unpulled.items > 0 then
upstream.unpulled = state.upstream.unpulled
end

state.cwd = cwd
state.head = head
state.upstream = upstream
state.untracked.items = untracked_files
state.unstaged.items = unstaged_files
state.staged.items = staged_files
Expand Down
Loading