Skip to content

Commit

Permalink
feat: experimental support for git operations (#290)
Browse files Browse the repository at this point in the history
  • Loading branch information
stevearc committed Apr 19, 2024
1 parent 354c530 commit 1f05774
Show file tree
Hide file tree
Showing 5 changed files with 184 additions and 1 deletion.
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,19 @@ require("oil").setup({
{ "name", "asc" },
},
},
-- EXPERIMENTAL support for performing file operations with git
git = {
-- Return true to automatically git add/mv/rm files
add = function(path)
return false
end,
mv = function(src_path, dest_path)
return false
end,
rm = function(path)
return false
end,
},
-- Configuration for the floating window in oil.open_float
float = {
-- Padding around the floating window
Expand Down
13 changes: 13 additions & 0 deletions doc/oil.txt
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,19 @@ CONFIG *oil-confi
{ "name", "asc" },
},
},
-- EXPERIMENTAL support for performing file operations with git
git = {
-- Return true to automatically git add/mv/rm files
add = function(path)
return false
end,
mv = function(src_path, dest_path)
return false
end,
rm = function(path)
return false
end,
},
-- Configuration for the floating window in oil.open_float
float = {
-- Padding around the floating window
Expand Down
31 changes: 30 additions & 1 deletion lua/oil/adapters/files.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ local columns = require("oil.columns")
local config = require("oil.config")
local constants = require("oil.constants")
local fs = require("oil.fs")
local git = require("oil.git")
local permissions = require("oil.adapters.files.permissions")
local trash = require("oil.adapters.files.trash")
local util = require("oil.util")
Expand Down Expand Up @@ -476,6 +477,18 @@ M.perform_action = function(action, cb)
local _, path = util.parse_url(action.url)
assert(path)
path = fs.posix_to_os_path(path)

if config.git.add(path) then
local old_cb = cb
cb = vim.schedule_wrap(function(err)
if not err then
git.add(path, old_cb)
else
old_cb(err)
end
end)
end

if action.entry_type == "directory" then
uv.fs_mkdir(path, 493, function(err)
-- Ignore if the directory already exists
Expand Down Expand Up @@ -503,6 +516,18 @@ M.perform_action = function(action, cb)
local _, path = util.parse_url(action.url)
assert(path)
path = fs.posix_to_os_path(path)

if config.git.rm(path) then
local old_cb = cb
cb = function(err)
if not err then
git.rm(path, old_cb)
else
old_cb(err)
end
end
end

if config.delete_to_trash then
if config.trash_command then
vim.notify_once(
Expand All @@ -525,7 +550,11 @@ M.perform_action = function(action, cb)
assert(dest_path)
src_path = fs.posix_to_os_path(src_path)
dest_path = fs.posix_to_os_path(dest_path)
fs.recursive_move(action.entry_type, src_path, dest_path, cb)
if config.git.mv(src_path, dest_path) then
git.mv(action.entry_type, src_path, dest_path, cb)
else
fs.recursive_move(action.entry_type, src_path, dest_path, cb)
end
else
-- We should never hit this because we don't implement supported_cross_adapter_actions
cb("files adapter doesn't support cross-adapter move")
Expand Down
13 changes: 13 additions & 0 deletions lua/oil/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,19 @@ local default_config = {
{ "name", "asc" },
},
},
-- EXPERIMENTAL support for performing file operations with git
git = {
-- Return true to automatically git add/mv/rm files
add = function(path)
return false
end,
mv = function(src_path, dest_path)
return false
end,
rm = function(path)
return false
end,
},
-- Configuration for the floating window in oil.open_float
float = {
-- Padding around the floating window
Expand Down
115 changes: 115 additions & 0 deletions lua/oil/git.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
-- integration with git operations
local fs = require("oil.fs")

local M = {}

---@param path string
---@return string|nil
M.get_root = function(path)
local git_dir = vim.fs.find(".git", { upward = true, path = path })[1]
if git_dir then
return vim.fs.dirname(git_dir)
else
return nil
end
end

---@param path string
---@param cb fun(err: nil|string)
M.add = function(path, cb)
local root = M.get_root(path)
if not root then
return cb()
end

local stderr = ""
local jid = vim.fn.jobstart({ "git", "add", path }, {
cwd = root,
stderr_buffered = true,
on_stderr = function(_, data)
stderr = table.concat(data, "\n")
end,
on_exit = function(_, code)
if code ~= 0 then
cb("Error in git add: " .. stderr)
else
cb()
end
end,
})
if jid <= 0 then
cb()
end
end

---@param path string
---@param cb fun(err: nil|string)
M.rm = function(path, cb)
local root = M.get_root(path)
if not root then
return cb()
end

local stderr = ""
local jid = vim.fn.jobstart({ "git", "rm", "-r", path }, {
cwd = root,
stderr_buffered = true,
on_stderr = function(_, data)
stderr = table.concat(data, "\n")
end,
on_exit = function(_, code)
if code ~= 0 then
stderr = vim.trim(stderr)
if stderr:match("^fatal: pathspec '.*' did not match any files$") then
cb()
else
cb("Error in git rm: " .. stderr)
end
else
cb()
end
end,
})
if jid <= 0 then
cb()
end
end

---@param entry_type oil.EntryType
---@param src_path string
---@param dest_path string
---@param cb fun(err: nil|string)
M.mv = function(entry_type, src_path, dest_path, cb)
local src_git = M.get_root(src_path)
if not src_git or src_git ~= M.get_root(dest_path) then
fs.recursive_move(entry_type, src_path, dest_path, cb)
return
end

local stderr = ""
local jid = vim.fn.jobstart({ "git", "mv", src_path, dest_path }, {
cwd = src_git,
stderr_buffered = true,
on_stderr = function(_, data)
stderr = table.concat(data, "\n")
end,
on_exit = function(_, code)
if code ~= 0 then
stderr = vim.trim(stderr)
if stderr:match("^fatal: not under version control") then
fs.recursive_move(entry_type, src_path, dest_path, cb)
else
cb("Error in git mv: " .. stderr)
end
else
cb()
end
end,
})
if jid <= 0 then
-- Failed to run git, fall back to normal filesystem operations
fs.recursive_move(entry_type, src_path, dest_path, cb)
end
end

return M

0 comments on commit 1f05774

Please sign in to comment.