diff --git a/lua/fff/main.lua b/lua/fff/main.lua index b90806e6..af2e7816 100644 --- a/lua/fff/main.lua +++ b/lua/fff/main.lua @@ -45,9 +45,23 @@ end --- @deprecated Use `find_files` instead function M.find_in_git_root() local fuzzy = require('fff.core').ensure_initialized() + pcall(fuzzy.wait_for_initial_scan, 5000) + local ok, git_root = pcall(fuzzy.get_git_root) - if not ok or not git_root then + if (not ok or not git_root or git_root == '') and vim.system then + local result = vim.system({ 'git', 'rev-parse', '--show-toplevel' }, { + cwd = vim.fn.getcwd(), + text = true, + }):wait() + + if result.code == 0 and result.stdout and result.stdout ~= '' then + git_root = result.stdout:gsub('%s+$', '') + ok = true + end + end + + if not ok or not git_root or git_root == '' then vim.notify('Not in a git repository', vim.log.levels.WARN) return end diff --git a/tests/find_in_git_root_spec.lua b/tests/find_in_git_root_spec.lua new file mode 100644 index 00000000..f43eb624 --- /dev/null +++ b/tests/find_in_git_root_spec.lua @@ -0,0 +1,100 @@ +---@diagnostic disable: undefined-global + +describe('find_in_git_root', function() + local main + local old_notify + local old_system + local old_getcwd + local old_find_files_in_dir + local notifications + local opened_dir + + before_each(function() + package.loaded['fff.main'] = nil + package.loaded['fff.core'] = nil + notifications = {} + opened_dir = nil + old_notify = vim.notify + old_system = vim.system + old_getcwd = vim.fn.getcwd + vim.notify = function(msg, level) + table.insert(notifications, { msg = msg, level = level }) + end + vim.fn.getcwd = function() + return '/repo/subdir' + end + end) + + after_each(function() + vim.notify = old_notify + vim.system = old_system + vim.fn.getcwd = old_getcwd + package.loaded['fff.main'] = nil + package.loaded['fff.core'] = nil + end) + + it('falls back to git rev-parse when git root is not ready yet', function() + package.loaded['fff.core'] = { + ensure_initialized = function() + return { + wait_for_initial_scan = function() return false end, + get_git_root = function() return nil end, + } + end, + } + + vim.system = function(cmd, opts) + assert.are.same({ 'git', 'rev-parse', '--show-toplevel' }, cmd) + assert.are.equal('/repo/subdir', opts.cwd) + return { + wait = function() + return { code = 0, stdout = '/repo\n' } + end, + } + end + + main = require('fff.main') + old_find_files_in_dir = main.find_files_in_dir + main.find_files_in_dir = function(dir) + opened_dir = dir + end + + main.find_in_git_root() + + assert.are.equal('/repo', opened_dir) + assert.are.equal(0, #notifications) + main.find_files_in_dir = old_find_files_in_dir + end) + + it('warns when neither cached git root nor fallback command succeeds', function() + package.loaded['fff.core'] = { + ensure_initialized = function() + return { + wait_for_initial_scan = function() return false end, + get_git_root = function() return nil end, + } + end, + } + + vim.system = function() + return { + wait = function() + return { code = 128, stdout = '' } + end, + } + end + + main = require('fff.main') + old_find_files_in_dir = main.find_files_in_dir + main.find_files_in_dir = function(dir) + opened_dir = dir + end + + main.find_in_git_root() + + assert.is_nil(opened_dir) + assert.are.equal(1, #notifications) + assert.are.equal('Not in a git repository', notifications[1].msg) + main.find_files_in_dir = old_find_files_in_dir + end) +end)