use-package icon indicating copy to clipboard operation
use-package copied to clipboard

:pin option ignored when trying to install newer version of builtin packages

Open markokocic opened this issue 2 years ago • 6 comments

I have the following in my config where is gnu defined to point to gnu elpa repository.

(use-package org :pin gnu)

Expected result: org-mode is installed and loaded from the repository specified with :pin.

Actual result: use-package loads builtin version of org that is bundled with Emacs itself.

Solutions: If :pin option is used, use-package should not allow loading specified package from other sources, including builtin packages.

Note: This is related to #319 but not specific to org-mode since it applies to all packages.

markokocic avatar Oct 01 '21 14:10 markokocic

Another scenario is installing project.el from GNU ELPA. project.el

(use-package project
  :pin gnu)

just keeps the built-in project.el.

manufactory avatar Oct 11 '21 15:10 manufactory

Just to reply to myself, I worked around this by having the following in my init file:

(defun mk/ignore-builtin (pkg)
  (assq-delete-all pkg package--builtins)
  (assq-delete-all pkg package--builtin-versions))

(mk/ignore-builtin 'org)
(use-package org ....)

This will ensure that org is removed from the list of Emacs builtins before calling use-package.

Since this is a relatively common problem, it would be good if we had use-package supportin this use case natively, by adding a new option like :ignore-builtin t

markokocic avatar Jul 13 '22 09:07 markokocic

Maybe I'm missing something here, but I don't think :pin ever supported upgrading packages? It sounds like you should just use M-x list-packages and upgrade packages in the normal way here, no?

skangas avatar Nov 30 '22 17:11 skangas

Regardless which version you installed or upgraded from the M-x list-packages screen. Upon restarting emacs, use-package will ignore :pin and just load builtin version if it exists.

Snippet from https://github.com/jwiegley/use-package/issues/955#issuecomment-1183003690 works around this, but it would be nice if use-package would natively support overriding builtin packages, since people that add use-package snippet in their .emacs file usually expect to load the latest version from elpa, like for any other package, and not from the emacs builtin disribution.

markokocic avatar Nov 30 '22 17:11 markokocic

I use Emacs on multiple machines and copy my config manually without the elpa directory. Thanks to use-package, my init.el downloads and installs everything I need the first time I start Emacs.

Except for org. I just tested again and even with :pin gnu I get version 9.5.5 (9.6 is in ELPA as of the time of this writing).

As a user, :pin seems like the intuitive way to solve this. :ignore-builtin t feels more like a workaround, but I'd take that if it let me upgrade org with use-package.

Spauldo avatar Dec 07 '22 08:12 Spauldo

You know, I didn't think until after I wrote this to check if package--builtins and package--builtin-versions were dynamically scoped (they are). I could have replaced this whole macro with a let statement. This works though and I've got work to do, so I'm leaving this here in case it helps someone else.

I can delete my ~/.emacs.d/elpa directory, start Emacs, and have my full config including the ELPA version of org-mode. I assume this would work with other builtins that are also in ELPA.

(defmacro with-ignored-builtin-package (pkg &rest body)
  "Ignore builtin PKG while executing BODY."
  (declare (indent defun))
  (let ((pb-orig (gensym))
        (pbv-orig (gensym))
	(ret (gensym)))
    `(let ((,pb-orig package--builtins)
           (,pbv-orig package--builtin-versions))
       (unless package--builtins
         (package-initialize))
       (setf package--builtins
             (assoc-delete-all ,pkg package--builtins))
       (setf package--builtin-versions
             (assoc-delete-all ,pkg package--builtin-versions))
       (setf ,ret (progn ,@body))
       (setf package--builtins ,pb-orig)
       (setf package--builtin-versions ,pbv-orig)
       ,ret)))

Then all you have to do to get org-mode is something like this:

(with-ignored-builtin-package 'org
  (use-package org
    :pin gnu
    :ensure t
    :hook (org-mode . jds/org-mode-hook)
    :init
    (setq org-latex-classes nil)
    :custom
    (org-src-fontify-natively t)
    (org-babel-load-languages '((C . t)
                                (emacs-lisp . t)
                                (fortran . t)
                                (lisp . t)
                                (maxima . t)
                                (perl . t)
                                (scheme . t)
                                (shell . t)))))

Remember to put it high in your config file so Emacs doesn't load the built-in org-mode first, otherwise you might get weird stuff like (void-function org-assert-version).

Spauldo avatar Dec 07 '22 12:12 Spauldo