package-vc-upgrade 出现 (error "File is not under version control") 的一种可能原因

今天在使用 package-vc-upgrade 更新一个包时,意外出现了 File is not under version control 的报错,但是这个包是使用 package-vc-install 直接从 github 链接安装的,而且之前调用这个函数也没有出现过问题。当我在 list-packages 得到的 buffer 中调用该命令时能够正常拉取,但是在 current-buffer 为我的 init.el 时调用该命令会报错。

用 edebug 调试了一下,发现虽然 package-vc-install 在调用 vc-pull 时将 default-directory 设置为了包所在的目录,但是 vc-pull 内部使用的 vc-deduce-fileset 会通过 with-current-buffer 设置当前 buffer 为当前 buffer (草):

;;vc.el line 1125
(with-current-buffer (or (buffer-base-buffer) (current-buffer))
      (setq res
            (vc-deduce-fileset-1 not-state-changing
                                 allow-unregistered
                                 state-model-only-files))
      (setq new-buf (current-buffer)))
...)

然后问题就出在了这个 vc-deduce-fileset-1 上,它在获取版本管理后端时使用 buffer-file-name 作为判断依据先于 default-directory ,因此我们调用 package-vc-upgrade 时所在的 buffer 将会提供这个 buffer-file-name ,从而导致可能的版本管理后端获取失败。

好玩的是如果我们所在的当前 buffer 是某个 git 仓库下的文件,那么 package-vc-upgrade 也能够正常工作,因为能够从当前文件获取到 Git 后端。这也大概是我之前没有碰到这个问题的原因,之前我在使用 git 管理配置文件,每次执行 package-vc-upgrade 都是在配置文件作为 current-buffer 时。

以下是一个复现过程:

  1. 在 Emacs 中随意打开一个文件,该文件没有位于任何的版本管理中
  2. 调用 package-vc-install 随便安装一个包,比如
    (package-vc-install "https://github.com/SqrtMinusOne/micromamba.el")
    
  3. 在先前打开的文件 buffer 作为当前 buffer 的情况下,调用 package-vc-upgrade 命令,并选择安装的包:micromamba
  4. 观察是否出现错误

要解决这个问题,比较简单的办法是加一个 around advice,使用 temp buffer 作为当前 buffer:

(defun yy/package-vc-upgrade-advice (upfun pkg-desc)
  (with-temp-buffer
    (funcall upfun pkg-desc)))
(advice-add 'package-vc-upgrade :around 'yy/package-vc-upgrade-advice)

如果你能够复现这个问题,可以回个帖告诉我,我会考虑提个 issue 给 bug-gnu-emacs。

顺带,使用的 Emacs 是 “GNU Emacs 29.2 (build 2, x86_64-w64-mingw32) of 2024-01-19”

1 个赞

bug#70526: 29.2; package-vc-upgrade failed with error message "File is n (gnu.org)

fixed: Always update VC packages from a vc-dir buffer