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.
This commit is contained in:
Evgeni Chasnovski
2025-11-16 20:27:19 +02:00
committed by GitHub
parent e6cdb7d481
commit e4e6605943
3 changed files with 31 additions and 27 deletions

View File

@@ -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 plugin's name in specification. It is assumed that all plugins in the
directory are managed exclusively by `vim.pack`. directory are managed exclusively by `vim.pack`.
Uses Git to manage plugins and requires present `git` executable of at least Uses Git to manage plugins and requires present `git` executable. Target
version 2.36. Target plugins should be Git repositories with versions as named plugins should be Git repositories with versions as named tags following
tags following semver convention `v<major>.<minor>.<patch>`. semver convention `v<major>.<minor>.<patch>`.
The latest state of all managed plugins is stored inside a *vim.pack-lockfile* 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 located at `$XDG_CONFIG_HOME/nvim/nvim-pack-lock.json`. It is a JSON file that

View File

@@ -417,21 +417,11 @@ local function check_external_tools()
health.warn('ripgrep not available') health.warn('ripgrep not available')
end 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 if vim.fn.executable('git') == 1 then
local git = vim.fn.exepath('git') local git = vim.fn.exepath('git')
local out = vim.system({ 'git', 'version' }, {}):wait().stdout or '' local version = vim.system({ 'git', 'version' }, {}):wait().stdout or ''
local version = vim.version.parse(out) health.ok(('%s (%s)'):format(vim.trim(version), git))
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
else else
health.warn('git not available (required by `vim.pack`)') health.warn('git not available (required by `vim.pack`)')
end end

View File

@@ -10,9 +10,9 @@
---Plugin's subdirectory name matches plugin's name in specification. ---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`. ---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 ---Uses Git to manage plugins and requires present `git` executable.
---least version 2.36. Target plugins should be Git repositories with versions ---Target plugins should be Git repositories with versions as named tags
---as named tags following semver convention `v<major>.<minor>.<patch>`. ---following semver convention `v<major>.<minor>.<patch>`.
--- ---
---The latest state of all managed plugins is stored inside a [vim.pack-lockfile]() ---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 ---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+$', '')) return (stdout:gsub('\n+$', ''))
end end
local git_version = vim.version.parse('1')
local function git_ensure_exec() 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') error('No `git` executable')
end end
end end
@@ -172,14 +176,17 @@ end
--- @param url string --- @param url string
--- @param path string --- @param path string
local function git_clone(url, path) 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 if vim.startswith(url, 'file://') then
cmd[#cmd + 1] = '--no-hardlinks' cmd[#cmd + 1] = '--no-hardlinks'
else else
-- NOTE: '--also-filter-submodules' requires Git>=2.36 if git_version >= vim.version.parse('2.36') then
local filter_args = { '--filter=blob:none', '--recurse-submodules', '--also-filter-submodules' } cmd[#cmd + 1] = '--filter=blob:none'
vim.list_extend(cmd, filter_args) cmd[#cmd + 1] = '--also-filter-submodules'
elseif git_version >= vim.version.parse('2.27') then
cmd[#cmd + 1] = '--filter=blob:none'
end
end end
vim.list_extend(cmd, { '--origin', 'origin', url, path }) vim.list_extend(cmd, { '--origin', 'origin', url, path })
@@ -618,8 +625,12 @@ end
local function checkout(p, timestamp) local function checkout(p, timestamp)
infer_revisions(p) infer_revisions(p)
local msg = ('vim.pack: %s Stash before checkout'):format(timestamp) local stash_cmd = { 'stash', '--quiet' }
git_cmd({ 'stash', '--quiet', '--message', msg }, p.path) 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) git_cmd({ 'checkout', '--quiet', p.info.sha_target }, p.path)
@@ -693,7 +704,10 @@ local function infer_update_details(p)
return return
end 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 cur_tags = git_cmd({ 'tag', '--list', '--points-at', sha_head }, p.path)
local past_tags = vim.split(older_tags, '\n') local past_tags = vim.split(older_tags, '\n')
vim.list_extend(past_tags, vim.split(cur_tags, '\n')) vim.list_extend(past_tags, vim.split(cur_tags, '\n'))