Skip to content
Open
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/oil/adapters/files.lua
Original file line number Diff line number Diff line change
Expand Up @@ -580,14 +580,14 @@ M.perform_action = function(action, cb)
end

if action.entry_type == "directory" then
uv.fs_mkdir(path, 493, function(err)
uv.fs_mkdir(path, 511, function(err)
-- Ignore if the directory already exists
if not err or err:match("^EEXIST:") then
cb()
else
cb(err)
end
end) -- 0755
end) -- 0777, filtered by the process umask
elseif action.entry_type == "link" and action.link then
local flags = nil
local target = fs.posix_to_os_path(action.link)
Expand Down
4 changes: 2 additions & 2 deletions lua/oil/adapters/trash/mac.lua
Original file line number Diff line number Diff line change
Expand Up @@ -152,14 +152,14 @@ M.perform_action = function(action, cb)
assert(path)
path = trash_dir .. path
if action.entry_type == "directory" then
uv.fs_mkdir(path, 493, function(err)
uv.fs_mkdir(path, 511, function(err)
-- Ignore if the directory already exists
if not err or err:match("^EEXIST:") then
cb()
else
cb(err)
end
end) -- 0755
end) -- 0777, filtered by the process umask
elseif action.entry_type == "link" and action.link then
local flags = nil
local target = fs.posix_to_os_path(action.link)
Expand Down
4 changes: 2 additions & 2 deletions lua/oil/fs.lua
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ end
---@param path string
---@param cb fun(err: nil|string)
M.touch = function(path, cb)
uv.fs_open(path, "a", 420, function(err, fd) -- 0644
uv.fs_open(path, "a", 438, function(err, fd) -- 0666, filtered by the process umask
if err then
cb(err)
else
Expand Down Expand Up @@ -147,7 +147,7 @@ end
---@param dir string
---@param mode? integer
M.mkdirp = function(dir, mode)
mode = mode or 493
mode = mode or 511 -- 0777, filtered by the process umask
local mod = ""
local path = dir
while vim.fn.isdirectory(path) == 0 do
Expand Down
36 changes: 36 additions & 0 deletions tests/files_spec.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
require("plenary.async").tests.add_to_env()
local TmpDir = require("tests.tmpdir")
local files = require("oil.adapters.files")
local fs = require("oil.fs")
local test_util = require("tests.test_util")

a.describe("files adapter", function()
Expand Down Expand Up @@ -49,6 +50,41 @@ a.describe("files adapter", function()
})
end)

if not fs.is_windows then
a.it("Creates files and directories using the process umask", function()
-- On Unix, luv implements fs_open/fs_mkdir with open(2)/mkdir(2), which apply umask.
-- Windows does not have Unix mode bits, and libuv currently ignores the mkdir mode there.
for _, case in ipairs({
{ umask = "0002", file_mode = 436, directory_mode = 509 }, -- 0664, 0775
{ umask = "0022", file_mode = 420, directory_mode = 493 }, -- 0644, 0755
}) do
local cmd = {
"sh",
"-c",
'umask "$1"; shift; exec "$@"',
"sh",
case.umask,
vim.v.progpath,
"--headless",
"-i",
"NONE",
"-u",
"tests/minimal_init.lua",
"-c",
string.format(
"lua require('tests.umask_case').run(%d, %d)",
case.file_mode,
case.directory_mode
),
"-c",
"qa!",
}
local output = vim.fn.system(cmd)
assert.equals(0, vim.v.shell_error, output)
end
end)
end

a.it("Deletes files", function()
tmpdir:create({ "a.txt" })
a.util.scheduler()
Expand Down
66 changes: 66 additions & 0 deletions tests/umask_case.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
local files = require("oil.adapters.files")
local fs = require("oil.fs")

local uv = vim.uv or vim.loop

local M = {}

local function create(action)
local done = false
local action_err
files.perform_action(action, function(err)
action_err = err
done = true
end)
assert(
vim.wait(1000, function()
return done
end),
"Timed out creating " .. action.url
)
assert(not action_err, action_err)
end

local function get_mode(path)
local stat = assert(uv.fs_stat(path))
return bit.band(stat.mode, 511)
end

function M.run(expected_file_mode, expected_directory_mode)
local root = vim.fn.tempname()
local file_path = fs.join(root, "file")
local directory_path = fs.join(root, "directory")
assert(uv.fs_mkdir(root, 511))

local ok, err = xpcall(function()
create({
url = "oil://" .. fs.os_to_posix_path(file_path),
entry_type = "file",
type = "create",
})
create({
url = "oil://" .. fs.os_to_posix_path(directory_path),
entry_type = "directory",
type = "create",
})
assert(
get_mode(file_path) == expected_file_mode,
string.format("Expected file mode %o, got %o", expected_file_mode, get_mode(file_path))
)
assert(
get_mode(directory_path) == expected_directory_mode,
string.format(
"Expected directory mode %o, got %o",
expected_directory_mode,
get_mode(directory_path)
)
)
end, debug.traceback)

uv.fs_unlink(file_path)
uv.fs_rmdir(directory_path)
uv.fs_rmdir(root)
assert(ok, err)
end

return M
Loading