neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

commit e4e6605943665c2f7b3bb9f7e2b065188935bd33
parent e6cdb7d481949ce02037d48bdde1d6b37289bd5a
Author: Evgeni Chasnovski <evgeni.chasnovski@gmail.com>
Date:   Sun, 16 Nov 2025 20:27:19 +0200

fix(pack): relax minimal Git version to be 2.0 #36573

Problem: Current requirement is Git>=2.36 as `--also-filter-submodules`
  flag for `git clone` was introduced there. This is problematic since
  default Git version on Ubuntu 22.04 is 2.34.

Solution: Relax minimal Git version to be (at least) 2.0 by selectively
  applying necessary flags based on the current Git version.
  As 2.0.0 was released in 2014-05-28 (almost the same age as Neovim
  project itself), it is reasonable to drop any mention and checks on
  minimal version altogether.
Diffstat:
Mruntime/doc/pack.txt | 6+++---
Mruntime/lua/vim/health/health.lua | 16+++-------------
Mruntime/lua/vim/pack.lua | 36+++++++++++++++++++++++++-----------
3 files changed, 31 insertions(+), 27 deletions(-)

diff --git a/runtime/doc/pack.txt b/runtime/doc/pack.txt @@ -217,9 +217,9 @@ or setting |$XDG_DATA_HOME| during startup. Plugin's subdirectory name matches plugin's name in specification. It is assumed that all plugins in the directory are managed exclusively by `vim.pack`. -Uses Git to manage plugins and requires present `git` executable of at least -version 2.36. Target plugins should be Git repositories with versions as named -tags following semver convention `v<major>.<minor>.<patch>`. +Uses Git to manage plugins and requires present `git` executable. Target +plugins should be Git repositories with versions as named tags following +semver convention `v<major>.<minor>.<patch>`. The latest state of all managed plugins is stored inside a *vim.pack-lockfile* located at `$XDG_CONFIG_HOME/nvim/nvim-pack-lock.json`. It is a JSON file that diff --git a/runtime/lua/vim/health/health.lua b/runtime/lua/vim/health/health.lua @@ -417,21 +417,11 @@ local function check_external_tools() health.warn('ripgrep not available') end - -- `vim.pack` requires `git` executable with version at least 2.36 + -- `vim.pack` prefers git 2.36 but tries to work with 2.x. if vim.fn.executable('git') == 1 then local git = vim.fn.exepath('git') - local out = vim.system({ 'git', 'version' }, {}):wait().stdout or '' - local version = vim.version.parse(out) - if version < vim.version.parse('2.36') then - local msg = string.format( - 'git is available (%s), but needs at least version 2.36 (not %s) to work with `vim.pack`', - git, - tostring(version) - ) - health.warn(msg) - else - health.ok(('%s (%s)'):format(vim.trim(out), git)) - end + local version = vim.system({ 'git', 'version' }, {}):wait().stdout or '' + health.ok(('%s (%s)'):format(vim.trim(version), git)) else health.warn('git not available (required by `vim.pack`)') end diff --git a/runtime/lua/vim/pack.lua b/runtime/lua/vim/pack.lua @@ -10,9 +10,9 @@ ---Plugin's subdirectory name matches plugin's name in specification. ---It is assumed that all plugins in the directory are managed exclusively by `vim.pack`. --- ----Uses Git to manage plugins and requires present `git` executable of at ----least version 2.36. Target plugins should be Git repositories with versions ----as named tags following semver convention `v<major>.<minor>.<patch>`. +---Uses Git to manage plugins and requires present `git` executable. +---Target plugins should be Git repositories with versions as named tags +---following semver convention `v<major>.<minor>.<patch>`. --- ---The latest state of all managed plugins is stored inside a [vim.pack-lockfile]() ---located at `$XDG_CONFIG_HOME/nvim/nvim-pack-lock.json`. It is a JSON file that @@ -162,8 +162,12 @@ local function git_cmd(cmd, cwd) return (stdout:gsub('\n+$', '')) end +local git_version = vim.version.parse('1') + local function git_ensure_exec() - if vim.fn.executable('git') == 0 then + local sys_res = vim.system({ 'git', 'version' }):wait() + git_version = vim.version.parse(sys_res.stdout) + if sys_res.stderr ~= '' then error('No `git` executable') end end @@ -172,14 +176,17 @@ end --- @param url string --- @param path string local function git_clone(url, path) - local cmd = { 'clone', '--quiet', '--origin', 'origin', '--no-checkout' } + local cmd = { 'clone', '--quiet', '--no-checkout', '--recurse-submodules' } if vim.startswith(url, 'file://') then cmd[#cmd + 1] = '--no-hardlinks' else - -- NOTE: '--also-filter-submodules' requires Git>=2.36 - local filter_args = { '--filter=blob:none', '--recurse-submodules', '--also-filter-submodules' } - vim.list_extend(cmd, filter_args) + if git_version >= vim.version.parse('2.36') then + cmd[#cmd + 1] = '--filter=blob:none' + cmd[#cmd + 1] = '--also-filter-submodules' + elseif git_version >= vim.version.parse('2.27') then + cmd[#cmd + 1] = '--filter=blob:none' + end end vim.list_extend(cmd, { '--origin', 'origin', url, path }) @@ -618,8 +625,12 @@ end local function checkout(p, timestamp) infer_revisions(p) - local msg = ('vim.pack: %s Stash before checkout'):format(timestamp) - git_cmd({ 'stash', '--quiet', '--message', msg }, p.path) + local stash_cmd = { 'stash', '--quiet' } + if git_version > vim.version.parse('2.13') then + stash_cmd[#stash_cmd + 1] = '--message' + stash_cmd[#stash_cmd + 1] = ('vim.pack: %s Stash before checkout'):format(timestamp) + end + git_cmd(stash_cmd, p.path) git_cmd({ 'checkout', '--quiet', p.info.sha_target }, p.path) @@ -693,7 +704,10 @@ local function infer_update_details(p) return end - local older_tags = git_cmd({ 'tag', '--list', '--no-contains', sha_head }, p.path) + local older_tags = '' + if git_version >= vim.version.parse('2.13') then + older_tags = git_cmd({ 'tag', '--list', '--no-contains', sha_head }, p.path) + end local cur_tags = git_cmd({ 'tag', '--list', '--points-at', sha_head }, p.path) local past_tags = vim.split(older_tags, '\n') vim.list_extend(past_tags, vim.split(cur_tags, '\n'))