diff --git a/lua/neogit/autocmds.lua b/lua/neogit/autocmds.lua index edcd7926c..e821a9a96 100644 --- a/lua/neogit/autocmds.lua +++ b/lua/neogit/autocmds.lua @@ -7,6 +7,21 @@ function M.setup() local status_buffer = require("neogit.buffers.status") local git = require("neogit.lib.git") local group = require("neogit").autocmd_group + local config = require("neogit.config") + + if config.values.auto_fetch_enabled and config.values.auto_fetch_on_startup then + api.nvim_create_autocmd("VimEnter", { + callback = function() + if git.cli.is_inside_worktree(".") then + local repo = require("neogit.lib.git.repository").instance(".") + vim.schedule(function() + repo:_fetch() + end) + end + end, + group = group, + }) + end api.nvim_create_autocmd({ "ColorScheme" }, { callback = function() diff --git a/lua/neogit/config.lua b/lua/neogit/config.lua index fd979e712..44aab80f0 100644 --- a/lua/neogit/config.lua +++ b/lua/neogit/config.lua @@ -332,6 +332,9 @@ end ---@field disable_signs? boolean Special signs to draw for sections etc. in Neogit ---@field prompt_force_push? boolean Offer to force push when branches diverge ---@field git_services? table Templartes to use when opening a pull request for a branch +---@field auto_fetch_enabled? boolean Enable/disable automatic fetching +---@field auto_fetch_interval? integer The interval (in milliseconds) for automatic fetching +---@field auto_fetch_on_startup? boolean Perform an initial fetch when Neogit starts ---@field fetch_after_checkout? boolean Perform a fetch if the newly checked out branch has an upstream or pushRemote set ---@field telescope_sorter? function The sorter telescope will use ---@field process_spinner? boolean Hide/Show the process spinner @@ -399,6 +402,9 @@ function M.get_default_values() disable_insert_on_commit = "auto", use_per_project_settings = true, remember_settings = true, + auto_fetch_enabled = false, + auto_fetch_interval = 300000, -- 5 minutes in milliseconds + auto_fetch_on_startup = false, fetch_after_checkout = false, sort_branches = "-committerdate", kind = "tab", @@ -1132,6 +1138,9 @@ function M.validate_config() end if validate_type(config, "base config", "table") then + validate_type(config.auto_fetch_enabled, "auto_fetch_enabled", "boolean") + validate_type(config.auto_fetch_interval, "auto_fetch_interval", "number") + validate_type(config.auto_fetch_on_startup, "auto_fetch_on_startup", "boolean") validate_type(config.disable_hint, "disable_hint", "boolean") validate_type(config.disable_context_highlighting, "disable_context_highlighting", "boolean") validate_type(config.disable_signs, "disable_signs", "boolean") diff --git a/lua/neogit/lib/git/fetch.lua b/lua/neogit/lib/git/fetch.lua index 332c1333b..f4240cab4 100644 --- a/lua/neogit/lib/git/fetch.lua +++ b/lua/neogit/lib/git/fetch.lua @@ -12,11 +12,16 @@ function M.fetch_interactive(remote, branch, args) return git.cli.fetch.args(remote or "", branch or "").arg_list(args).call { pty = true } end ----@param remote string ----@param branch string ----@return ProcessResult +---@param remote string | nil +---@param branch string | nil function M.fetch(remote, branch) - return git.cli.fetch.args(remote, branch).call { ignore_error = true } + local result = git.cli.fetch.args(remote, branch).call { ignore_error = true } + + if result and result.code == 0 then + return true, result + else + return false, result + end end return M diff --git a/lua/neogit/lib/git/repository.lua b/lua/neogit/lib/git/repository.lua index a8e55fcc4..67b6fd1ee 100644 --- a/lua/neogit/lib/git/repository.lua +++ b/lua/neogit/lib/git/repository.lua @@ -4,6 +4,8 @@ local Path = require("plenary.path") local git = require("neogit.lib.git") local ItemFilter = require("neogit.lib.item_filter") local util = require("neogit.lib.util") +local notification = require("neogit.lib.notification") +local event = require("neogit.lib.event") local modules = { "status", @@ -169,6 +171,10 @@ local function empty_state() } end +---@class NeogitRepoAutoFetch +---@field timer uv_timer_t +---@field interval integer + ---@class NeogitRepo ---@field lib table ---@field state NeogitRepoState @@ -179,6 +185,7 @@ end ---@field interrupt table ---@field tmp_state table ---@field refresh_callbacks function[] +---@field auto_fetch NeogitRepoAutoFetch|nil local Repo = {} Repo.__index = Repo @@ -219,6 +226,7 @@ function Repo.new(dir) running = util.weak_table(), interrupt = util.weak_table(), tmp_state = util.weak_table("v"), + auto_fetch = nil, } instance.state.worktree_root = instance.worktree_root @@ -231,6 +239,10 @@ function Repo.new(dir) require("neogit.lib.git." .. m).register(instance.lib) end + if instance.worktree_root ~= "" then + instance:_setup_auto_fetch() + end + return instance end @@ -344,4 +356,74 @@ Repo.dispatch_refresh = a.void(function(self, opts) self:refresh(opts) end) +function Repo:_setup_auto_fetch() + local config = require("neogit.config") + + if config.values.auto_fetch_enabled then + logger.debug("[REPO]: Setting up auto-fetch for " .. self.worktree_root) + + self.auto_fetch = { + timer = vim.uv.new_timer(), + interval = config.values.auto_fetch_interval, + } + + self:_start_auto_fetch() + end +end + +function Repo:_start_auto_fetch() + if not self.auto_fetch then + return + end + + logger.debug("[REPO]: Starting auto-fetch timer") + + self.auto_fetch.timer:start( + self.auto_fetch.interval, + self.auto_fetch.interval, + vim.schedule_wrap(function() + self:_fetch() + end) + ) +end + +function Repo:_fetch() + notification.info("Auto-fetching...") + a.void(function() + local success, result = git.fetch.fetch("--all") + + if success then + notification.info("Auto-fetch complete.") + else + local error_message = "Auto-fetch failed: " + if result then + if result.stderr and #result.stderr > 0 then + if type(result.stderr) == "table" then + error_message = error_message .. table.concat(result.stderr, "\n") + elseif type(result.stderr) == "string" then + error_message = error_message .. result.stderr + else + error_message = error_message .. "Unknown stderr format." + end + elseif result.stdout and #result.stdout > 0 then + if type(result.stdout) == "table" then + error_message = error_message .. table.concat(result.stdout, "\n") + elseif type(result.stdout) == "string" then + error_message = error_message .. result.stdout + else + error_message = error_message .. "Unknown stdout format." + end + else + error_message = error_message + .. string.format("Command failed with exit code %d", result.code or -1) + end + else + error_message = error_message .. "No result returned from git command." + end + notification.error(error_message) + end + event.send("FetchComplete") + end)() +end + return Repo