Skip to content

Commit

Permalink
refactor: replace disable_changes with an error filter
Browse files Browse the repository at this point in the history
  • Loading branch information
stevearc committed Oct 21, 2023
1 parent 781caf1 commit 26704f4
Show file tree
Hide file tree
Showing 5 changed files with 15 additions and 155 deletions.
12 changes: 10 additions & 2 deletions lua/oil/adapters/trash/freedesktop.lua
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ local FIELD_META = constants.FIELD_META

local M = {}

M.disable_changes = true

local function touch_dir(path)
uv.fs_mkdir(path, 448) -- 0700
end
Expand All @@ -37,6 +35,7 @@ local function get_home_trash_dir()
end

---@param mode integer
---@return boolean
local function is_sticky(mode)
local extra = bit.rshift(mode, 9)
return bit.band(extra, 4) ~= 0
Expand Down Expand Up @@ -422,6 +421,15 @@ M.filter_action = function(action)
end
end

---@param err oil.ParseError
---@return boolean
M.filter_error = function(err)
if err.message == "Duplicate filename" then
return false
end
return true
end

---@param action oil.Action
---@return string
M.render_action = function(action)
Expand Down
2 changes: 1 addition & 1 deletion lua/oil/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ local M = {}
---@field read_file? fun(bufnr: integer) Used for adapters that deal with remote/virtual files. Read the contents of the file into a buffer.
---@field write_file? fun(bufnr: integer) Used for adapters that deal with remote/virtual files. Write the contents of a buffer to the destination.
---@field supported_cross_adapter_actions? table<string, oil.CrossAdapterAction> Mapping of adapter name to enum for all other adapters that can be used as a src or dest for move/copy actions.
---@field disable_changes? boolean When true, adapter will not support creating new entries or changing (e.g. renaming) existing entries
---@field filter_action? fun(action: oil.Action): boolean When present, filter out actions as they are created
---@field filter_error? fun(action: oil.ParseError): boolean When present, filter out errors from parsing a buffer

-- TODO remove after https://github.com/folke/neodev.nvim/pull/163 lands
---@diagnostic disable: undefined-field
Expand Down
4 changes: 4 additions & 0 deletions lua/oil/mutator/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,10 @@ M.try_write_changes = function(confirm)
if vim.bo[bufnr].modified then
local diffs, errors = parser.parse(bufnr)
all_diffs[bufnr] = diffs
local adapter = assert(util.get_adapter(bufnr))
if adapter.filter_error then
errors = vim.tbl_filter(adapter.filter_error, errors)
end
if not vim.tbl_isempty(errors) then
all_errors[bufnr] = errors
end
Expand Down
68 changes: 0 additions & 68 deletions lua/oil/mutator/parser.lua
Original file line number Diff line number Diff line change
Expand Up @@ -142,70 +142,6 @@ M.parse_line = function(adapter, line, column_defs)
return { data = ret, entry = entry, ranges = ranges }
end

---@param bufnr integer
---@param adapter oil.Adapter
---@return oil.Diff[]
---@return oil.ParseError[] errors Parsing errors
local function parse_lines_for_no_change_adapter(bufnr, adapter)
---@type oil.Diff[]
local diffs = {}
---@type oil.ParseError[]
local errors = {}
local bufname = vim.api.nvim_buf_get_name(bufnr)
local scheme, path = util.parse_url(bufname)
local parent_url = scheme .. path
local children = cache.list_url(parent_url)
---@type table<integer, boolean>
local original_ids = {}
for _, entry in pairs(children) do
original_ids[entry[FIELD_ID]] = true
end

local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, true)
for i, line in ipairs(lines) do
local id_str = line:match("^/(%d+) ")
if id_str then
local id = assert(tonumber(id_str))
local entry = cache.get_entry_by_id(id)
if not entry then
table.insert(errors, {
lnum = i - 1,
col = 0,
message = "Invalid file ID",
})
else
if original_ids[id] then
original_ids[id] = nil
else
local other_parent_url = cache.get_parent_url(id)
local other_adapter = assert(config.get_adapter_by_scheme(other_parent_url))
-- Ignore new entries if they're from the same adapter (e.g. moving/copying around in
-- the trash). We only care about moving in from a *different* adapter.
if adapter ~= other_adapter then
table.insert(diffs, {
type = "new",
id = entry[FIELD_ID],
name = entry[FIELD_NAME],
entry_type = entry[FIELD_TYPE],
})
end
end
end
end
end

for id in pairs(original_ids) do
local entry = assert(cache.get_entry_by_id(id))
table.insert(diffs, {
type = "delete",
name = entry[FIELD_NAME],
id = id,
})
end

return diffs, errors
end

---@class (exact) oil.ParseError
---@field lnum integer
---@field col integer
Expand All @@ -230,10 +166,6 @@ M.parse = function(bufnr)
return diffs, errors
end

if adapter.disable_changes then
return parse_lines_for_no_change_adapter(bufnr, adapter)
end

local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, true)
local scheme, path = util.parse_url(bufname)
local column_defs = columns.get_supported_columns(adapter)
Expand Down
84 changes: 0 additions & 84 deletions tests/parser_spec.lua
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
require("plenary.async").tests.add_to_env()
local cache = require("oil.cache")
local constants = require("oil.constants")
local parser = require("oil.mutator.parser")
local test_adapter = require("oil.adapters.test")
Expand Down Expand Up @@ -244,87 +243,4 @@ describe("parser", function()
local diffs = parser.parse(bufnr)
assert.are.same({}, diffs)
end)

describe("disable_changes adapter", function()
before_each(function()
test_adapter.disable_changes = true
end)

after_each(function()
test_adapter.disable_changes = nil
end)

it("ignores new files", function()
vim.cmd.edit({ args = { "oil-test:///foo/" } })
local bufnr = vim.api.nvim_get_current_buf()
local lines = { "newentry" }
set_lines(bufnr, lines)
local diffs, errors = parser.parse(bufnr)
assert.are.same({}, diffs)
assert.are.same({}, errors)
end)

it("detects new entries", function()
vim.cmd.edit({ args = { "oil-test:///foo/" } })
local bufnr = vim.api.nvim_get_current_buf()
local file = cache.create_and_store_entry("oil:///root/", "newentry", "file")
local cols = view.format_entry_cols(file, {}, {}, test_adapter)
local lines = util.render_table({ cols }, {})
set_lines(bufnr, lines)
local diffs, errors = parser.parse(bufnr)
assert.are.same({
{
id = file[FIELD_ID],
type = "new",
name = "newentry",
entry_type = "file",
},
}, diffs)
assert.are.same({}, errors)
end)

it("ignores name changes", function()
vim.cmd.edit({ args = { "oil-test:///dir/" } })
local bufnr = vim.api.nvim_get_current_buf()
local file = test_adapter.test_set("/dir/foo.txt", "file")
local lines = {
string.format("/%d newname", file[FIELD_ID]),
}
set_lines(bufnr, lines)
local diffs, errors = parser.parse(bufnr)
assert.are.same({}, diffs)
assert.are.same({}, errors)
end)

it("tolerates files with the same name", function()
vim.cmd.edit({ args = { "oil-test:///dir/" } })
local bufnr = vim.api.nvim_get_current_buf()
local file = test_adapter.test_set("/dir/foo.txt", "file")
local file2 = test_adapter.test_set("/dir/bar.txt", "file")
local lines = {
string.format("/%d newname", file[FIELD_ID]),
string.format("/%d newname", file2[FIELD_ID]),
}
set_lines(bufnr, lines)
local diffs, errors = parser.parse(bufnr)
assert.are.same({}, diffs)
assert.are.same({}, errors)
end)

it("ignores duplicate entries", function()
vim.cmd.edit({ args = { "oil-test:///dir/" } })
local bufnr = vim.api.nvim_get_current_buf()
local file = test_adapter.test_set("/dir/foo.txt", "file")
local lines = {
string.format("/%d newname", file[FIELD_ID]),
string.format("/%d newname", file[FIELD_ID]),
string.format("/%d newname", file[FIELD_ID]),
string.format("/%d newname", file[FIELD_ID]),
}
set_lines(bufnr, lines)
local diffs, errors = parser.parse(bufnr)
assert.are.same({}, diffs)
assert.are.same({}, errors)
end)
end)
end)

0 comments on commit 26704f4

Please sign in to comment.