From 48f1216eab14c9a392bf2d86fbd00b9361850c39 Mon Sep 17 00:00:00 2001 From: Ross Williams Date: Thu, 15 Dec 2022 17:19:08 -0500 Subject: [PATCH] Pull upstream force-pushed Git tags Resolves #1100. Pull upstream tags even if they were force-pushed. Git version 2.20 changed the behavior of fetching tags so that non-fast-forward updates would fail. Some plugin authors, like `nvim-tree/nvim-tree.lua` use a tag named `nightly` that is force-pushed with latest updates to provide bleeding-edge changes. By adding an explicit refspec to the `git fetch` command line with a leading plus-sign ('+') Git will always update the tag to the new commit, regardless of whether it was force-pushed upstream. See https://www.git-scm.com/docs/git-fetch#Documentation/git-fetch.txt-ltrefspecgt for details (paragraph beginning "Until Git version 2.20..."). --- lua/packer/plugin_types/git.lua | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/lua/packer/plugin_types/git.lua b/lua/packer/plugin_types/git.lua index 011efe6fa..931884a04 100644 --- a/lua/packer/plugin_types/git.lua +++ b/lua/packer/plugin_types/git.lua @@ -380,8 +380,18 @@ git.setup = function(plugin) options = { env = git.job_env }, } + -- If a tag is specified, name its refspec on the update + -- or fetch command line with a leading plus-sign ('+') to ensure that + -- upstream commits are pull/fetch-ed even if upstream force-pushed. + -- Not needed for branches, because in that case pulling force-pushed + -- commits is the default. + local explicit_refspec = '' + if plugin.tag then + explicit_refspec = fmt(' origin +refs/tags/%s', plugin.tag) + end + if needs_checkout then - r:and_then(await, jobs.run(config.exec_cmd .. config.subcommands.fetch, update_opts)) + r:and_then(await, jobs.run(fetch_cmd .. explicit_refspec, update_opts)) r:and_then(await, handle_checkouts(plugin, install_to, disp, opts)) local function merge_output(res) if res.output ~= nil then @@ -406,13 +416,13 @@ git.setup = function(plugin) if opts.preview_updates then disp:task_update(plugin_name, 'fetching updates...') - r:and_then(await, jobs.run(fetch_cmd, update_opts)) + r:and_then(await, jobs.run(fetch_cmd .. explicit_refspec, update_opts)) elseif opts.pull_head then disp:task_update(plugin_name, 'pulling updates from head...') r:and_then(await, jobs.run(update_head_cmd, update_opts)) else disp:task_update(plugin_name, 'pulling updates...') - r:and_then(await, jobs.run(update_cmd, update_opts)):and_then(await, jobs.run(submodule_cmd, update_opts)) + r:and_then(await, jobs.run(update_cmd .. explicit_refspec, update_opts)):and_then(await, jobs.run(submodule_cmd, update_opts)) end r:map_err(function(err) plugin.output = { err = vim.list_extend(update_info.err, update_info.output), data = {} }