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
13 changes: 11 additions & 2 deletions lua/diffview/scene/file_entry.lua
Original file line number Diff line number Diff line change
Expand Up @@ -98,14 +98,23 @@ function FileEntry:init(opt)
self._extra_owned = opt._extra_owned or {}
end

---Destroy owned Files. `force` still drops COMMIT/STAGE/CUSTOM buffers
---unconditionally, but LOCAL buffers stay guarded by `is_buf_in_use`: they
---represent the user's real file buffer and may be visible in windows
---outside the diffview (e.g., the tab the user opened from). Force-deleting
---one would collapse that tab and lose the cursor position there.
---@param force? boolean
function FileEntry:destroy(force)
local function force_for(f)
return force and f.rev and f.rev.type ~= RevType.LOCAL
end

for _, f in ipairs(self.layout:owned_files()) do
f:destroy(force)
f:destroy(force_for(f))
end

for _, f in ipairs(self._extra_owned) do
f:destroy(force)
f:destroy(force_for(f))
end
self._extra_owned = {}

Expand Down
59 changes: 57 additions & 2 deletions lua/diffview/tests/functional/file_entry_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -425,17 +425,29 @@ describe("diffview.scene.file_entry", function()
eq(0, #entry._extra_owned)
end)

it("forwards force flag to contained files when destroyed", function()
it("forwards force to non-LOCAL files but guards LOCAL when destroyed", function()
local seen = {}
local layout_destroyed = false

-- LOCAL files stand in for the user's real working-tree buffer, which
-- may be visible in other tabs; `FileEntry:destroy` must never propagate
-- `force=true` to them. Non-LOCAL sides (STAGE/COMMIT) remain forced so
-- `refresh_files({ force = true })` still discards their virtual buffers.
local files_list = {
{
rev = { type = RevType.STAGE },
destroy = function(_, force)
seen[#seen + 1] = force
end,
},
{
rev = { type = RevType.LOCAL },
destroy = function(_, force)
seen[#seen + 1] = force
end,
},
{
rev = { type = RevType.COMMIT },
destroy = function(_, force)
seen[#seen + 1] = force
end,
Expand Down Expand Up @@ -466,7 +478,50 @@ describe("diffview.scene.file_entry", function()

entry:destroy(true)

eq({ true, true }, seen)
eq({ true, false, true }, seen)
eq(true, layout_destroyed)
end)

it("passes force=false through unchanged regardless of rev type", function()
local seen = {}

local files_list = {
{
rev = { type = RevType.STAGE },
destroy = function(_, force)
seen[#seen + 1] = force
end,
},
{
rev = { type = RevType.LOCAL },
destroy = function(_, force)
seen[#seen + 1] = force
end,
},
}
local layout = {
files = function()
return files_list
end,
owned_files = function()
return files_list
end,
destroy = function() end,
}

local entry = FileEntry({
adapter = { ctx = { toplevel = "/tmp" } },
path = "a.txt",
oldpath = nil,
revs = {},
layout = layout,
status = "M",
stats = {},
kind = "working",
})

entry:destroy(false)

eq({ false, false }, seen)
end)
end)
Loading