一份简易的包管理思路

大多数 Emacs 用户可能有遇到过以下:

  1. 如果更换了设备, Emacs 如何保持一样的开发环境?
  2. Emacs配置是否因为某次删除 .emacs.d/ 重新使用Emacs导致配置错误, 苦苦查找错误?
  3. 因为更新某个包因与当前Emacs版本不兼容, 但又丢失了之前版本的包?
  4. 或许使用过 git 方式管理包, 但由于各种依赖放弃git方法
  5. 或许你讨厌 git 方式太占用硬盘空间了

所以你想要一个, 更换设备/重构.emacs.d 后Emacs还能保持原来那样使用, 固定包版本, 不再花费更多时间去苦苦查找配置问题.

思路大概如下:

  1. 固定包来源的版本
  2. 将包保存在本地

请将一下代码放到你的配置当中:

(eval-and-compile
  (customize-set-variable
   'package-archives '(("melpa" . "https://raw.githubusercontent.com/d12frosted/elpa-mirror/master/melpa/");; 2023-09-07
                       ("org"   . "https://raw.githubusercontent.com/d12frosted/elpa-mirror/master/org/");; 2023-09-07
                       ("gnu"   . "https://raw.githubusercontent.com/d12frosted/elpa-mirror/master/gnu/");; 2023-09-07
                       ;; ("melpa-pin" . "https://raw.githubusercontent.com/d12frosted/elpa-mirror/b7a0f0e122aa8c4f868afc62fe14b1475e617666/melpa/");; 2022-06-05
                       ;; ("gnu-pin" . "https://raw.githubusercontent.com/d12frosted/elpa-mirror/b7a0f0e122aa8c4f868afc62fe14b1475e617666/gnu/");; 2022-06-05
                       ;; ("org-pin" . "https://raw.githubusercontent.com/d12frosted/elpa-mirror/b7a0f0e122aa8c4f868afc62fe14b1475e617666/org/");; 2022-06-05
                       ))
  ;; (package-initialize);; Emacs >= 28+ don't need
  ;; (unless (package-installed-p 'elpa-mirror);; 如果还没有该包将执行以下代码
  ;;   (customize-set-variable
  ;;    'package-archives '(("elpa-local-30" . "~/.emacs.d/.local/elpa-local-30/")))
  ;;   (package-refresh-contents)
  ;;   (package-install 'elpa-mirror))
  )

elpa-mirror 这包是用来 将 .emacs.d/elpa 下的全部包打包保存在另外一个地方, 供本地使用
如果你使用 elpa-mirror, 可以将上面的注释去掉, 这样重构 .emacs.d/ 时, 自动使用本地的包快速恢复

;; Emacs版本小于29 需要先安装 use-package
(use-package elpa-mirror
  :ensure t
  :commands (elpamr-create-mirror-for-installed)
  :custom
  (elpamr-default-output-directory (format "%s.local/elpa-local-30" user-emacs-directory)))
;; 感谢 陈斌 大大!!

如果有包没有提交到 melpa 等(无法直接从 Emacs 中安装), 可以将该包 *.el 文件全部下载放到以下目录, 往后直接 (require 'your-package) 调用即可

;; 以下代码来源于 懒猫大大, 感谢!
;; 递归遍历加载路径
(defun add-subdirs-to-load-path(dir)
  "Recursive add directories to `load-path`."
  (let ((default-directory (file-name-as-directory dir)))
    (add-to-list 'load-path dir)
    (normal-top-level-add-subdirs-to-load-path)))
;; 设置load-path
(let ((gc-cons-threshold most-positive-fixnum)
      (file-name-handler-alist nil))
  (add-subdirs-to-load-path "~/.emacs.d/core-30/"))

如果你想下载不是最新的包, 可以使用 use-package :pin 关键字来安装, 例如:

(use-package pyim
  :ensure t
  :pin gnu-pin);; 对应 package-archives 变量

这样就可以避免很多关于如何管理包的问题了

与君共勉!!

1 个赞

这个场景感觉挺适合 straight 的,每次更新完依赖就调用 straight-freeze-versions 保存依赖版本信息。新设备直接按照对应版本拉取依赖。变更后 git 里面也有之前使用的版本信息,手动恢复下就可以。

分散在 wiki 里面的依赖,我就手动下下来放到 site-packages 目录里面,自己管理版本。

1 个赞