local M = {} local function has_valid_head(path) if vim.fn.isdirectory(path .. "/.git") == 0 then return true end vim.fn.system({ "git", "-C", path, "rev-parse", "--verify", "HEAD" }) return vim.v.shell_error == 0 end local function prune_broken_pack_repos() local root = vim.fn.stdpath("data") .. "/site/pack/core/opt" if vim.fn.isdirectory(root) == 0 then return end for _, dir in ipairs(vim.fn.readdir(root)) do local path = root .. "/" .. dir if vim.fn.isdirectory(path) == 1 and not has_valid_head(path) then vim.fn.delete(path, "rf") end end end local function to_src(value) if value:match("^[%w+.-]+://") or value:match("^git@") then return value end return "https://github.com/" .. value end function M.add(specs) local resolved = {} for _, spec in ipairs(specs) do if type(spec) == "string" then table.insert(resolved, to_src(spec)) else local plugin = vim.deepcopy(spec) plugin.src = to_src(plugin.src) table.insert(resolved, plugin) end end local ok, err = pcall(vim.pack.add, resolved, { confirm = false, load = true }) if not ok and tostring(err):find("ambiguous argument 'HEAD'", 1, true) then prune_broken_pack_repos() vim.fn.delete(vim.fn.stdpath("config") .. "/nvim-pack-lock.json") ok, err = pcall(vim.pack.add, resolved, { confirm = false, load = true }) end if not ok then vim.schedule(function() local msg = "vim.pack failed to install/load plugins. Check network and run :lua vim.pack.update()." vim.notify(msg .. "\n" .. tostring(err), vim.log.levels.WARN) end) return false end return true end return M