Skip to content

Commit b0cc22f

Browse files
committed
feat(git): Get all file history data with a single job
Further improves the stability of the history updating process. - Implement empty log entries (some commits may be identical to their parent. And some merge commits may not list any changes depending on the value of `--diff-merges`, but they should still be included in the history). - Changed default options for single file history: - `--follow` is now set by default. - `--diff-merges` is set to `first-parent` by default.
1 parent 94f5f40 commit b0cc22f

File tree

7 files changed

+482
-270
lines changed

7 files changed

+482
-270
lines changed

lua/diffview/config.lua

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,8 @@ M.defaults = {
8383
---@type ConfigLogOptions
8484
git = {
8585
single_file = {
86-
diff_merges = "combined",
86+
diff_merges = "first-parent",
87+
follow = true,
8788
},
8889
multi_file = {
8990
diff_merges = "first-parent",

lua/diffview/scene/file_entry.lua

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
local lazy = require("diffview.lazy")
22
local oop = require("diffview.oop")
33

4+
local Diff1 = lazy.access("diffview.scene.layouts.diff_1", "Diff1") ---@type Diff1|LazyModule
45
local Diff2 = lazy.access("diffview.scene.layouts.diff_2", "Diff2") ---@type Diff2|LazyModule
56
local File = lazy.access("diffview.vcs.file", "File") ---@type vcs.File|LazyModule
67
local RevType = lazy.access("diffview.vcs.rev", "RevType") ---@type RevType|LazyModule
@@ -279,6 +280,11 @@ function FileEntry:has_patch_folds()
279280
return true
280281
end
281282

283+
---@return boolean
284+
function FileEntry:is_null_entry()
285+
return self.path == "null" and self.layout:get_main_win().file == File.NULL_FILE
286+
end
287+
282288
---@static
283289
---@param adapter VCSAdapter
284290
function FileEntry.update_index_stat(adapter, stat)
@@ -336,5 +342,19 @@ function FileEntry.with_layout(layout_class, opt)
336342
})
337343
end
338344

345+
function FileEntry.new_null_entry(adapter)
346+
return FileEntry({
347+
adapter = adapter,
348+
path = "null",
349+
kind = "working",
350+
binary = false,
351+
nulled = true,
352+
layout = Diff1({
353+
b = File.NULL_FILE,
354+
})
355+
})
356+
end
357+
339358
M.FileEntry = FileEntry
359+
340360
return M

lua/diffview/scene/views/file_history/render.lua

Lines changed: 64 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ local config = require("diffview.config")
33
local hl = require("diffview.hl")
44
local utils = require("diffview.utils")
55

6+
local fmt = string.format
67
local logger = DiffviewGlobal.logger
78
local perf = PerfTimer("[FileHistoryPanel] Render internal")
89
local pl = utils.path
@@ -15,23 +16,32 @@ local function render_files(comp, files)
1516
for i, file in ipairs(files) do
1617
comp:add_text(i == #files and "" or "", "DiffviewNonText")
1718

18-
if file.status then
19-
comp:add_text(file.status .. " ", hl.get_git_hl(file.status))
20-
end
19+
if file:is_null_entry() then
20+
comp:add_text(
21+
"No diff",
22+
file.active and "DiffviewFilePanelSelected" or "DiffviewFilePanelFileName"
23+
)
24+
else
25+
if file.status then
26+
comp:add_text(file.status .. " ", hl.get_git_hl(file.status))
27+
else
28+
comp:add_text("-" .. " ", "DiffviewNonText")
29+
end
2130

22-
local icon, icon_hl = hl.get_file_icon(file.basename, file.extension)
23-
comp:add_text(icon, icon_hl)
31+
local icon, icon_hl = hl.get_file_icon(file.basename, file.extension)
32+
comp:add_text(icon, icon_hl)
2433

25-
if #file.parent_path > 0 then
26-
comp:add_text(file.parent_path .. "/", "DiffviewFilePanelPath")
27-
end
34+
if #file.parent_path > 0 then
35+
comp:add_text(file.parent_path .. "/", "DiffviewFilePanelPath")
36+
end
2837

29-
comp:add_text(file.basename, file.active and "DiffviewFilePanelSelected" or "DiffviewFilePanelFileName")
38+
comp:add_text(file.basename, file.active and "DiffviewFilePanelSelected" or "DiffviewFilePanelFileName")
3039

31-
if file.stats then
32-
comp:add_text(" " .. file.stats.additions, "DiffviewFilePanelInsertions")
33-
comp:add_text(", ")
34-
comp:add_text(tostring(file.stats.deletions), "DiffviewFilePanelDeletions")
40+
if file.stats then
41+
comp:add_text(" " .. file.stats.additions, "DiffviewFilePanelInsertions")
42+
comp:add_text(", ")
43+
comp:add_text(tostring(file.stats.deletions), "DiffviewFilePanelDeletions")
44+
end
3545
end
3646

3747
comp:ln()
@@ -47,7 +57,7 @@ end
4757
local function render_entries(panel, parent, entries, updating)
4858
local c = config.get_config()
4959
local max_num_files = -1
50-
local max_len_stats = 7
60+
local max_len_stats = -1
5161

5262
for _, entry in ipairs(entries) do
5363
if #entry.files > max_num_files then
@@ -72,39 +82,60 @@ local function render_entries(panel, parent, entries, updating)
7282
end
7383

7484
local entry_struct = parent[i]
75-
local comp = entry_struct.commit.comp
85+
local comp = entry_struct.commit.comp --[[@as RenderComponent ]]
7686

7787
if not entry.single_file then
7888
comp:add_text((entry.folded and c.signs.fold_closed or c.signs.fold_open) .. " ", "CursorLineNr")
7989
end
8090

8191
if entry.status then
8292
comp:add_text(entry.status, hl.get_git_hl(entry.status))
93+
else
94+
comp:add_text("-", "DiffviewNonText")
8395
end
8496

8597
if not entry.single_file then
86-
local counter = " "
87-
.. utils.str_left_pad(tostring(#entry.files), #tostring(max_num_files))
88-
.. (" file%s"):format(#entry.files > 1 and "s" or " ")
89-
comp:add_text(counter, "DiffviewFilePanelCounter")
98+
local s_num_files = tostring(max_num_files)
99+
100+
if entry.nulled then
101+
comp:add_text(utils.str_center_pad("empty", #s_num_files + 7), "DiffviewFilePanelCounter")
102+
else
103+
comp:add_text(
104+
fmt(
105+
" %s file%s",
106+
utils.str_left_pad(tostring(#entry.files), #s_num_files),
107+
#entry.files > 1 and "s" or " "
108+
),
109+
"DiffviewFilePanelCounter"
110+
)
111+
end
90112
end
91113

92-
if entry.stats then
93-
local adds = tostring(entry.stats.additions)
94-
local dels = tostring(entry.stats.deletions)
95-
comp:add_text(" | ", "DiffviewNonText")
96-
comp:add_text(adds, "DiffviewFilePanelInsertions")
97-
comp:add_text(string.rep(" ", max_len_stats - (#adds + #dels)))
98-
comp:add_text(dels, "DiffviewFilePanelDeletions")
114+
if max_len_stats ~= -1 then
115+
local adds = { "-", "DiffviewNonText" }
116+
local dels = { "-", "DiffviewNonText" }
117+
118+
if entry.stats and entry.stats.additions then
119+
adds = { tostring(entry.stats.additions), "DiffviewFilePanelInsertions" }
120+
end
121+
122+
if entry.stats and entry.stats.deletions then
123+
dels = { tostring(entry.stats.deletions), "DiffviewFilePanelDeletions" }
124+
end
125+
99126
comp:add_text(" | ", "DiffviewNonText")
127+
comp:add_text(unpack(adds))
128+
comp:add_text(string.rep(" ", max_len_stats - (#adds[1] + #dels[1])))
129+
comp:add_text(unpack(dels))
130+
comp:add_text(" |", "DiffviewNonText")
100131
end
101132

102133
if entry.commit.hash then
103-
comp:add_text(entry.commit.hash:sub(1, 8) .. " ", "DiffviewSecondary")
134+
comp:add_text(" " .. entry.commit.hash:sub(1, 8), "DiffviewSecondary")
104135
end
105136

106137
if entry.commit.ref_names then
107-
comp:add_text(("(%s) "):format(entry.commit.ref_names), "DiffviewReference")
138+
comp:add_text((" (%s)"):format(entry.commit.ref_names), "DiffviewReference")
108139
end
109140

110141
local subject = utils.str_trunc(entry.commit.subject, 72)
@@ -114,18 +145,18 @@ local function render_entries(panel, parent, entries, updating)
114145
end
115146

116147
comp:add_text(
117-
subject .. " ",
148+
" " .. subject,
118149
panel.cur_item[1] == entry and "DiffviewFilePanelSelected" or "DiffviewFilePanelFileName"
119150
)
120151

121152
if entry.commit then
122153
-- 3 months
123154
local date = (
124-
os.difftime(os.time(), entry.commit.time) > 60 * 60 * 24 * 30 * 3
125-
and entry.commit.iso_date
155+
os.difftime(os.time(), entry.commit.time) > 60 * 60 * 24 * 30 * 3
156+
and entry.commit.iso_date
126157
or entry.commit.rel_date
127-
)
128-
comp:add_text(entry.commit.author .. ", " .. date, "DiffviewFilePanelPath")
158+
)
159+
comp:add_text(" " .. entry.commit.author .. ", " .. date, "DiffviewFilePanelPath")
129160
end
130161

131162
comp:ln()

lua/diffview/utils.lua

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -31,23 +31,14 @@ end
3131
---@param schedule? boolean Schedule the echo call.
3232
function M.echo_multiln(msg, hl, schedule)
3333
if schedule then
34-
vim.schedule(function()
35-
M.echo_multiln(msg, hl, false)
36-
end)
34+
vim.schedule(function() M.echo_multiln(msg, hl, false) end)
3735
return
3836
end
3937

40-
vim.cmd("echohl " .. (hl or "None"))
41-
if type(msg) ~= "table" then
42-
msg = { msg }
43-
end
44-
for _, chunk in ipairs(msg) do
45-
for _, line in ipairs(vim.split(chunk, "\n", { trimempty = false })) do
46-
line = line:gsub('["|\t]', { ['"'] = [[\"]], ["\t"] = " " })
47-
vim.cmd(string.format('echom "%s"', line))
48-
end
49-
end
50-
vim.cmd("echohl None")
38+
if type(msg) ~= "table" then msg = { msg } end
39+
40+
local text = table.concat(msg, "\n")
41+
api.nvim_echo({ { text, hl } }, true, {})
5142
end
5243

5344
---@param msg string|string[]
@@ -61,7 +52,7 @@ function M.info(msg, schedule)
6152
end
6253
msg = M.vec_slice(msg)
6354
msg[1] = "[Diffview.nvim] " .. msg[1]
64-
M.echo_multiln(msg, "Directory", schedule)
55+
M.echo_multiln(msg, "DiagnosticInfo", schedule)
6556
end
6657

6758
---@param msg string|string[]
@@ -1252,9 +1243,10 @@ function M.temp_win(bufnr, enter)
12521243
end
12531244

12541245
---Create a copy of `func` bound to the given arguments.
1255-
---@param func function
1246+
---@generic T
1247+
---@param func fun(...): T
12561248
---@param ... any Arguments to prepend to arguments provided to the bound function when invoking `func`.
1257-
---@return fun(...): unknown
1249+
---@return fun(...): T
12581250
function M.bind(func, ...)
12591251
local bound_args = M.tbl_pack(...)
12601252

0 commit comments

Comments
 (0)