local git = require("neo-tree.git") local parser = require("neo-tree.git.parser") local git_cmd = require("neo-tree.git.cmd") local utils = require("neo-tree.utils") local diff_base = nil local status_cache = {} local orig_find_status local function find_worktree_root() local root = git.find_worktree_info(vim.fn.getcwd()) if not root then local buf = vim.api.nvim_buf_get_name(0) if buf ~= "" then root = git.find_worktree_info(buf) end end return root end local function run_git(args) local result = vim.system(args):wait() if result.code ~= 0 then return nil end return result.stdout end local function compute_status(wr, base) local args = git_cmd.with_args({ "-C", wr, "diff", base, "--name-status", "-z" }) local out = run_git(args) if not out then vim.notify("DiffBase: invalid ref " .. base, vim.log.levels.WARN) return nil end local status = parser.parse_diff_name_status_output(wr, false, utils.gsplit_plain(out, "\000")) local ut = run_git(git_cmd.with_args({ "-C", wr, "ls-files", "--others", "--exclude-standard", "-z" })) if ut then for _, p in ipairs(parser.parse_ls_files_output(wr, utils.gsplit_plain(ut, "\000"))) do status[p] = "?" end end return status end local function patch() if not orig_find_status then orig_find_status = git.find_existing_status_code end git.find_existing_status_code = function(path, base_lookup) if diff_base then local wr, _ = git.find_existing_worktree(path) local cached = wr and status_cache[wr] local hit = cached and cached[path] if hit then return hit, true end end return orig_find_status(path, base_lookup) end end local function set(base) base = base or "" if base == "" or base == "HEAD" then diff_base = nil status_cache = {} pcall(function() require("gitsigns").change_base(nil, true) end) local e = require("neo-tree.events") vim.schedule(function() e.fire_event(e.GIT_EVENT, {}) end) vim.notify("DiffBase: reset to HEAD") return end local wr = find_worktree_root() if not wr then vim.notify("DiffBase: not in a git repo", vim.log.levels.WARN) return end local s = compute_status(wr, base) if not s then return end diff_base = base status_cache[wr] = s pcall(function() require("gitsigns").change_base(base, true) end) patch() local events = require("neo-tree.events") if git.worktrees[wr] then git.worktrees[wr].status = s end vim.schedule(function() events.fire_event(events.GIT_STATUS_CHANGED, { git_root = wr, git_status = s, base = base }) end) vim.notify("DiffBase: set to " .. base) end vim.api.nvim_create_user_command("DiffBase", function(opts) set(opts.args) end, { nargs = "?", complete = function(l) return vim.tbl_filter(function(s) return s:find(l, 1, true) == 1 end, { "HEAD", "HEAD~1", "HEAD~2", "HEAD~3", "main", "master", "origin/main", "origin/master" }) end, })