diff --git a/lua/nvim-tree/explorer/watch.lua b/lua/nvim-tree/explorer/watch.lua index 50afb5a3da8..727bb4781df 100644 --- a/lua/nvim-tree/explorer/watch.lua +++ b/lua/nvim-tree/explorer/watch.lua @@ -4,11 +4,7 @@ local Watcher = require("nvim-tree.watcher").Watcher local M = {} -local function is_git(path) - return vim.fn.fnamemodify(path, ":t") == ".git" -end - -local IGNORED_PATHS = { +M.ignore_dirs = { -- disable watchers on kernel filesystems -- which have a lot of unwanted events "/sys", @@ -16,13 +12,11 @@ local IGNORED_PATHS = { "/dev", } -local function is_folder_ignored(path) - for _, folder in ipairs(IGNORED_PATHS) do - if vim.startswith(path, folder) then - return true - end - end +function M.ignore_dir(path) + table.insert(M.ignore_dirs, path) +end +local function is_folder_ignored(path) for _, ignore_dir in ipairs(M.ignore_dirs) do if vim.fn.match(path, ignore_dir) ~= -1 then return true @@ -44,7 +38,7 @@ function M.create_watcher(node) path = node.absolute_path end - if is_git(path) or is_folder_ignored(path) then + if is_folder_ignored(path) then return nil end @@ -74,7 +68,7 @@ end function M.setup(opts) M.enabled = opts.filesystem_watchers.enable M.debounce_delay = opts.filesystem_watchers.debounce_delay - M.ignore_dirs = opts.filesystem_watchers.ignore_dirs + M.ignore_dirs = vim.tbl_extend("force", M.ignore_dirs, opts.filesystem_watchers.ignore_dirs) M.uid = 0 end diff --git a/lua/nvim-tree/git/init.lua b/lua/nvim-tree/git/init.lua index a843b00c11a..33d6b6c2cad 100644 --- a/lua/nvim-tree/git/init.lua +++ b/lua/nvim-tree/git/init.lua @@ -2,6 +2,7 @@ local log = require "nvim-tree.log" local utils = require "nvim-tree.utils" local git_utils = require "nvim-tree.git.utils" local Runner = require "nvim-tree.git.runner" +local Watch = require "nvim-tree.explorer.watch" local Watcher = require("nvim-tree.watcher").Watcher local Iterator = require "nvim-tree.iterators.node-iterator" local explorer_node = require "nvim-tree.explorer.node" @@ -164,22 +165,34 @@ function M.load_project_status(cwd) } local watcher = nil + if M.config.filesystem_watchers.enable then log.line("watcher", "git start") - local callback = function(w) - log.line("watcher", "git event scheduled '%s'", w.project_root) - utils.debounce("git:watcher:" .. w.project_root, M.config.filesystem_watchers.debounce_delay, function() - if w.destroyed then - return - end - reload_tree_at(w.project_root) - end) - end + local git_directory = git_utils.get_git_directory(project_root) + + if git_directory == nil then + log.line("watcher", "could not found the location of .git folder") + else + local callback = function(w) + log.line("watcher", "git event scheduled '%s'", w.project_root) + utils.debounce("git:watcher:" .. w.project_root, M.config.filesystem_watchers.debounce_delay, function() + if w.destroyed then + return + end + reload_tree_at(w.project_root) + end) + end + + -- Add GIT_DIR to the list of directory to ignore + -- local base_gitdir = utils.path_basename(git_directory) + -- Watch.ignore_dir(base_gitdir) + Watch.ignore_dir(git_directory) - watcher = Watcher:new(utils.path_join { project_root, ".git" }, WATCHED_FILES, callback, { - project_root = project_root, - }) + watcher = Watcher:new(git_directory, WATCHED_FILES, callback, { + project_root = project_root, + }) + end end M.projects[project_root] = { diff --git a/lua/nvim-tree/git/utils.lua b/lua/nvim-tree/git/utils.lua index 5ec0645dd79..41c8634942a 100644 --- a/lua/nvim-tree/git/utils.lua +++ b/lua/nvim-tree/git/utils.lua @@ -1,7 +1,6 @@ local M = {} local log = require "nvim-tree.log" - -local has_cygpath = vim.fn.executable "cygpath" == 1 +local utils = require "nvim-tree.utils" function M.get_toplevel(cwd) local profile = log.profile_start("git toplevel %s", cwd) @@ -18,16 +17,9 @@ function M.get_toplevel(cwd) return nil end - -- git always returns path with forward slashes - if vim.fn.has "win32" == 1 then - -- msys2 git support - if has_cygpath then - toplevel = vim.fn.system("cygpath -w " .. vim.fn.shellescape(toplevel)) - if vim.v.shell_error ~= 0 then - return nil - end - end - toplevel = toplevel:gsub("/", "\\") + toplevel = utils.norm_path(toplevel) + if toplevel == nil then + return nil end -- remove newline @@ -94,4 +86,28 @@ function M.file_status_to_dir_status(status, cwd) return r end +function M.get_git_directory(cwd) + local profile = log.profile_start("git directory %s", cwd) + + local cmd = { "git", "-C", cwd, "rev-parse", "--absolute-git-dir" } + log.line("git", vim.inspect(cmd)) + + local git_dir = vim.fn.system(cmd) + + log.raw("git", git_dir) + log.profile_end(profile) + + if vim.v.shell_error ~= 0 or not git_dir or #git_dir == 0 or git_dir:match "fatal" then + return nil + end + + git_dir = utils.norm_path(git_dir) + if git_dir == nil then + return nil + end + + -- remove newline + return git_dir:sub(0, -2) +end + return M diff --git a/lua/nvim-tree/utils.lua b/lua/nvim-tree/utils.lua index 608523a8072..46c0c427040 100644 --- a/lua/nvim-tree/utils.lua +++ b/lua/nvim-tree/utils.lua @@ -5,10 +5,11 @@ local M = { debouncers = {}, } +local has_cygpath = vim.fn.executable "cygpath" == 1 + M.is_unix = vim.fn.has "unix" == 1 M.is_macos = vim.fn.has "mac" == 1 or vim.fn.has "macunix" == 1 M.is_wsl = vim.fn.has "wsl" == 1 --- false for WSL M.is_windows = vim.fn.has "win32" == 1 or vim.fn.has "win32unix" == 1 function M.str_find(haystack, needle) @@ -38,6 +39,26 @@ function M.path_split(path) return path:gmatch("[^" .. path_separator .. "]+" .. path_separator .. "?") end +--- Normalise a path: +--- windows: replace slashes with backslashes +--- cygwin: resolve path first via cygpath +--- @param path string +--- @return string|nil nil on cygpath failure +function M.norm_path(path) + if M.is_windows then + -- msys2 git support + if has_cygpath then + path = vim.fn.system("cygpath -w " .. vim.fn.shellescape(path)) + if vim.v.shell_error ~= 0 then + return nil + end + end + path = path:gsub("/", "\\") + end + + return path +end + ---Get the basename of the given path. ---@param path string ---@return string