From 604e4cf4c8033358a6fd9616285a4a5c3d0c144c Mon Sep 17 00:00:00 2001 From: bhagwan Date: Tue, 19 Apr 2022 22:36:13 -0700 Subject: [PATCH] feat(git): added support for --git-dir, --work-tree (yadm) --- lua/fzf-lua/actions.lua | 16 ++++++------- lua/fzf-lua/config.lua | 2 +- lua/fzf-lua/core.lua | 2 ++ lua/fzf-lua/make_entry.lua | 2 +- lua/fzf-lua/path.lua | 43 ++++++++++++++++++++++++++--------- lua/fzf-lua/previewer/fzf.lua | 6 ++--- lua/fzf-lua/providers/git.lua | 24 ++++++++++++------- 7 files changed, 63 insertions(+), 32 deletions(-) diff --git a/lua/fzf-lua/actions.lua b/lua/fzf-lua/actions.lua index 535bebb..277d19a 100644 --- a/lua/fzf-lua/actions.lua +++ b/lua/fzf-lua/actions.lua @@ -432,11 +432,11 @@ end M.git_switch = function(selected, opts) - local cmd = path.git_cwd({"git", "checkout"}, opts.cwd) + local cmd = path.git_cwd({"git", "checkout"}, opts) local git_ver = utils.git_version() -- git switch was added with git version 2.23 if git_ver and git_ver >= 2.23 then - cmd = path.git_cwd({"git", "switch"}, opts.cwd) + cmd = path.git_cwd({"git", "switch"}, opts) end -- remove anything past space local branch = selected[1]:match("[^ ]+") @@ -456,8 +456,8 @@ M.git_switch = function(selected, opts) end M.git_checkout = function(selected, opts) - local cmd_checkout = path.git_cwd({"git", "checkout"}, opts.cwd) - local cmd_cur_commit = path.git_cwd({"git", "rev-parse", "--short HEAD"}, opts.cwd) + local cmd_checkout = path.git_cwd({"git", "checkout"}, opts) + local cmd_cur_commit = path.git_cwd({"git", "rev-parse", "--short HEAD"}, opts) local commit_hash = selected[1]:match("[^ ]+") if vim.fn.input("Checkout commit " .. commit_hash .. "? [y/n] ") == "y" then local current_commit = utils.io_systemlist(cmd_cur_commit) @@ -488,18 +488,18 @@ local git_exec = function(selected, opts, cmd) end M.git_stage = function(selected, opts) - local cmd = path.git_cwd({"git", "add", "--"}, opts.cwd) + local cmd = path.git_cwd({"git", "add", "--"}, opts) git_exec(selected, opts, cmd) end M.git_unstage = function(selected, opts) - local cmd = path.git_cwd({"git", "reset", "--"}, opts.cwd) + local cmd = path.git_cwd({"git", "reset", "--"}, opts) git_exec(selected, opts, cmd) end M.git_buf_edit = function(selected, opts) - local cmd = path.git_cwd({"git", "show"}, opts.cwd) - local git_root = path.git_root(opts.cwd, true) + local cmd = path.git_cwd({"git", "show"}, opts) + local git_root = path.git_root(opts, true) local win = vim.api.nvim_get_current_win() local buffer_filetype = vim.bo.filetype local file = path.relative(vim.fn.expand("%:p"), git_root) diff --git a/lua/fzf-lua/config.lua b/lua/fzf-lua/config.lua index 32ca32e..c1975e8 100644 --- a/lua/fzf-lua/config.lua +++ b/lua/fzf-lua/config.lua @@ -761,7 +761,7 @@ function M.normalize_opts(opts, defaults) end -- test for valid git_repo - opts.git_icons = opts.git_icons and path.is_git_repo(opts.cwd, true) + opts.git_icons = opts.git_icons and path.is_git_repo(opts, true) local executable = function(binary, fncerr, strerr) if binary and vim.fn.executable(binary) ~= 1 then diff --git a/lua/fzf-lua/core.lua b/lua/fzf-lua/core.lua index 048fb5a..5209bba 100644 --- a/lua/fzf-lua/core.lua +++ b/lua/fzf-lua/core.lua @@ -339,6 +339,8 @@ M.mt_cmd_wrapper = function(opts) "argv_expr", "cmd", "cwd", + "git_dir", + "git_worktree", "git_icons", "file_icons", "color_icons", diff --git a/lua/fzf-lua/make_entry.lua b/lua/fzf-lua/make_entry.lua index 379157e..865b36f 100644 --- a/lua/fzf-lua/make_entry.lua +++ b/lua/fzf-lua/make_entry.lua @@ -192,7 +192,7 @@ M.get_diff_files = function(opts) local diff_files = {} local cmd = opts.git_status_cmd or config.globals.files.git_status_cmd if not cmd then return {} end - local ok, status, err = pcall(utils.io_systemlist, path.git_cwd(cmd, opts.cwd)) + local ok, status, err = pcall(utils.io_systemlist, path.git_cwd(cmd, opts)) if ok and err == 0 then for i = 1, #status do local icon = status[i]:match("[MUDARC?]+") diff --git a/lua/fzf-lua/path.lua b/lua/fzf-lua/path.lua index c869fc2..eaede26 100644 --- a/lua/fzf-lua/path.lua +++ b/lua/fzf-lua/path.lua @@ -228,26 +228,47 @@ function M.entry_to_file(entry, cwd, force_uri) } end -function M.git_cwd(cmd, cwd) - if not cwd then return cmd end - cwd = vim.fn.expand(cwd) +function M.git_cwd(cmd, opts) + -- backward compat, used to be single cwd param + local o = opts or {} + if type(o) == 'string' then + o = { cwd = o } + end + local git_args = { + { "cwd", "-C" }, + { "git_dir", "--git-dir" }, + { "git_worktree", "--work-tree" }, + } if type(cmd) == 'string' then - local arg_cwd = ("-C %s "):format(vim.fn.shellescape(cwd)) - cmd = cmd:gsub("^git ", "git " .. arg_cwd) + local args = "" + for _, a in ipairs(git_args) do + if o[a[1]] then + o[a[1]] = vim.fn.expand(o[a[1]]) + args = args .. ("%s %s "):format(a[2], vim.fn.shellescape(o[a[1]])) + end + end + cmd = cmd:gsub("^git ", "git " .. args) else + local idx = 2 cmd = utils.tbl_deep_clone(cmd) - table.insert(cmd, 2, "-C") - table.insert(cmd, 3, cwd) + for _, a in ipairs(git_args) do + if o[a[1]] then + o[a[1]] = vim.fn.expand(o[a[1]]) + table.insert(cmd, idx, a[2]) + table.insert(cmd, idx+1, o[a[1]]) + idx = idx + 2 + end + end end return cmd end -function M.is_git_repo(cwd, noerr) - return not not M.git_root(cwd, noerr) +function M.is_git_repo(opts, noerr) + return not not M.git_root(opts, noerr) end -function M.git_root(cwd, noerr) - local cmd = M.git_cwd({"git", "rev-parse", "--show-toplevel"}, cwd) +function M.git_root(opts, noerr) + local cmd = M.git_cwd({"git", "rev-parse", "--show-toplevel"}, opts) local output, err = utils.io_systemlist(cmd) if err ~= 0 then if not noerr then utils.info(unpack(output)) end diff --git a/lua/fzf-lua/previewer/fzf.lua b/lua/fzf-lua/previewer/fzf.lua index 35a24d8..baf24af 100644 --- a/lua/fzf-lua/previewer/fzf.lua +++ b/lua/fzf-lua/previewer/fzf.lua @@ -239,9 +239,9 @@ Previewer.git_diff = Previewer.base:extend() function Previewer.git_diff:new(o, opts) Previewer.git_diff.super.new(self, o, opts) - self.cmd_deleted = path.git_cwd(o.cmd_deleted, opts.cwd) - self.cmd_modified = path.git_cwd(o.cmd_modified, opts.cwd) - self.cmd_untracked = path.git_cwd(o.cmd_untracked, opts.cwd) + self.cmd_deleted = path.git_cwd(o.cmd_deleted, opts) + self.cmd_modified = path.git_cwd(o.cmd_modified, opts) + self.cmd_untracked = path.git_cwd(o.cmd_untracked, opts) self.pager = o.pager do -- populate the icon mappings diff --git a/lua/fzf-lua/providers/git.lua b/lua/fzf-lua/providers/git.lua index 3ff0aa5..91281a8 100644 --- a/lua/fzf-lua/providers/git.lua +++ b/lua/fzf-lua/providers/git.lua @@ -8,10 +8,18 @@ local shell = require "fzf-lua.shell" local M = {} +local function set_git_cwd_args(opts) + opts.cwd = path.git_root(opts) + if opts.git_dir or opts.git_worktree then + opts.cmd = path.git_cwd(opts.cmd, opts) + end + return opts +end + M.files = function(opts) opts = config.normalize_opts(opts, config.globals.git.files) if not opts then return end - opts.cwd = path.git_root(opts.cwd) + opts = set_git_cwd_args(opts) if not opts.cwd then return end local contents = core.mt_cmd_wrapper(opts) opts = core.set_header(opts, 2) @@ -21,10 +29,10 @@ end M.status = function(opts) opts = config.normalize_opts(opts, config.globals.git.status) if not opts then return end - opts.cwd = path.git_root(opts.cwd) + opts = set_git_cwd_args(opts) if not opts.cwd then return end if opts.preview then - opts.preview = vim.fn.shellescape(path.git_cwd(opts.preview, opts.cwd)) + opts.preview = vim.fn.shellescape(path.git_cwd(opts.preview, opts)) end -- we don't need git icons since we get them -- as part of our `git status -s` @@ -76,7 +84,7 @@ M.status = function(opts) end local function git_cmd(opts) - opts.cwd = path.git_root(opts.cwd) + opts = set_git_cwd_args(opts) if not opts.cwd then return end opts = core.set_header(opts, 2) core.fzf_wrap(opts, opts.cmd, function(selected) @@ -88,14 +96,14 @@ end M.commits = function(opts) opts = config.normalize_opts(opts, config.globals.git.commits) if not opts then return end - opts.preview = vim.fn.shellescape(path.git_cwd(opts.preview, opts.cwd)) + opts.preview = vim.fn.shellescape(path.git_cwd(opts.preview, opts)) return git_cmd(opts) end M.bcommits = function(opts) opts = config.normalize_opts(opts, config.globals.git.bcommits) if not opts then return end - local git_root = path.git_root(opts.cwd) + local git_root = path.git_root(opts) if not git_root then return end local file = path.relative(vim.fn.expand("%:p"), git_root) opts.cmd = opts.cmd .. " " .. file @@ -104,7 +112,7 @@ M.bcommits = function(opts) if git_ver and git_ver >= 2.31 then opts.preview = opts.preview .. " --rotate-to=" .. vim.fn.shellescape(file) end - opts.preview = vim.fn.shellescape(path.git_cwd(opts.preview, opts.cwd)) + opts.preview = vim.fn.shellescape(path.git_cwd(opts.preview, opts)) return git_cmd(opts) end @@ -112,7 +120,7 @@ M.branches = function(opts) opts = config.normalize_opts(opts, config.globals.git.branches) if not opts then return end opts.fzf_opts["--no-multi"] = '' - opts._preview = path.git_cwd(opts.preview, opts.cwd) + opts._preview = path.git_cwd(opts.preview, opts) opts.preview = shell.preview_action_cmd(function(items) local branch = items[1]:gsub("%*", "") -- remove the * from current branch if branch:find("%)") ~= nil then