feat: add configurable file and directory creation permissions

Problem: files were always created with mode 0644 and directories
with 0755, hardcoded in fs.touch and uv.fs_mkdir. Users who need
different defaults (e.g. 0600 for security) had no config option.

Solution: add new_file_mode (default 420 = 0644) and new_dir_mode
(default 493 = 0755) config options, passed through to fs.touch and
uv.fs_mkdir in the files and mac trash adapters. The fs.touch
signature accepts an optional mode parameter with backwards
compatibility (detects function argument to support old callers).
Local cache directories (SSH, S3) continue using standard system
permissions rather than the user-configured mode.

Based on: stevearc/oil.nvim#537
This commit is contained in:
Barrett Ruth 2026-02-20 16:58:15 -05:00
parent ded17258cd
commit c6b4a7a07b
Signed by: barrett
GPG key ID: A6C96C9349D2FC81
5 changed files with 21 additions and 6 deletions

View file

@ -122,6 +122,10 @@ CONFIG *oil-confi
return nil
end,
},
-- Permission mode for new files (default 420 = 0644)
new_file_mode = 420,
-- Permission mode for new directories (default 493 = 0755)
new_dir_mode = 493,
-- Extra arguments to pass to SCP when moving/copying files over SSH
extra_scp_args = {},
-- Extra arguments to pass to aws s3 when creating/deleting/moving/copying files using aws s3

View file

@ -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, config.new_dir_mode, function(err)
-- Ignore if the directory already exists
if not err or err:match("^EEXIST:") then
cb()
else
cb(err)
end
end) -- 0755
end)
elseif action.entry_type == "link" and action.link then
local flags = nil
local target = fs.posix_to_os_path(action.link)
@ -600,7 +600,7 @@ M.perform_action = function(action, cb)
---@diagnostic disable-next-line: param-type-mismatch
uv.fs_symlink(target, path, flags, cb)
else
fs.touch(path, cb)
fs.touch(path, config.new_file_mode, cb)
end
elseif action.type == "delete" then
local _, path = util.parse_url(action.url)

View file

@ -166,7 +166,7 @@ M.perform_action = function(action, cb)
---@diagnostic disable-next-line: param-type-mismatch
uv.fs_symlink(target, path, flags, cb)
else
fs.touch(path, cb)
fs.touch(path, config.new_file_mode, cb)
end
elseif action.type == "delete" then
local _, path = util.parse_url(action.url)

View file

@ -105,6 +105,8 @@ local default_config = {
return nil
end,
},
new_file_mode = 420,
new_dir_mode = 493,
-- Extra arguments to pass to SCP when moving/copying files over SSH
extra_scp_args = {},
-- Extra arguments to pass to aws s3 when creating/deleting/moving/copying files using aws s3
@ -239,6 +241,8 @@ default_config.view_options.highlight_filename = nil
---@field keymaps table<string, any>
---@field use_default_keymaps boolean
---@field view_options oil.ViewOptions
---@field new_file_mode integer
---@field new_dir_mode integer
---@field extra_scp_args string[]
---@field extra_s3_args string[]
---@field git oil.GitOptions
@ -268,6 +272,8 @@ local M = {}
---@field keymaps? table<string, any>
---@field use_default_keymaps? boolean Set to false to disable all of the above keymaps
---@field view_options? oil.SetupViewOptions Configure which files are shown and how they are shown.
---@field new_file_mode? integer Permission mode for new files in decimal (default 420 = 0644)
---@field new_dir_mode? integer Permission mode for new directories in decimal (default 493 = 0755)
---@field extra_scp_args? string[] Extra arguments to pass to SCP when moving/copying files over SSH
---@field extra_s3_args? string[] Extra arguments to pass to aws s3 when moving/copying files using aws s3
---@field git? oil.SetupGitOptions EXPERIMENTAL support for performing file operations with git

View file

@ -37,9 +37,14 @@ M.abspath = function(path)
end
---@param path string
---@param mode? integer File mode in decimal (default 420 = 0644)
---@param cb fun(err: nil|string)
M.touch = function(path, cb)
uv.fs_open(path, "a", 420, function(err, fd) -- 0644
M.touch = function(path, mode, cb)
if type(mode) == "function" then
cb = mode
mode = 420
end
uv.fs_open(path, "a", mode or 420, function(err, fd)
if err then
cb(err)
else