Subject: Re: bug#62720: 29.0.60; Not easy at all to upgrade :core packages like Eglot

From: João Távora <[email-masked]>
Date: Mon, 10 Apr 2023 17:01:31 +0100

On Sat, Apr 8, 2023 at 4:45 PM Stefan Monnier <[email-masked]> wrote:
>
> > As package-update just defers to package-install, I don't find this
> > surprising.  What you want is that package.el always treats a built-in
> > package as upgradable to a package from ELPA.  It seems like this should
> > be possible by adjusting the interactive spec of package-install and
> > modifying package-compute-transaction or even package-built-in-p.
>
> I agree, tho I don't understand why you say "built-in" above.  Isn't the
> problem also present for already-installed-but-out-of-date ELPA packages?

I bit the bullet and went after this in package.el.  The answer is no,
it's not present for those packages.

But Philip's imagined fix seems to be more complicated than it needs
to be. Here's a simple patch that works well in my tests.  It makes
M-x package-update also update built-in-packages.

diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el
index f92afe56b76..f54b6f39e40 100644
--- a/lisp/emacs-lisp/package.el
+++ b/lisp/emacs-lisp/package.el
@@ -2243,11 +2243,16 @@ package-update
   (let* ((package (if (symbolp name)
                       name
                     (intern name)))
-         (pkg-desc (cadr (assq package package-alist))))
-    (if (package-vc-p pkg-desc)
-        (package-vc-update pkg-desc)
-      (package-delete pkg-desc 'force)
-      (package-install package 'dont-select))))
+         (nonbuiltin (assq package package-alist)))
+    (cond (nonbuiltin
+           (let ((desc (cadr nonbuiltin)))
+             (if (package-vc-p desc)
+                 (package-vc-update desc)
+               (package-delete desc 'force)
+               (package-install package 'dont-select))))
+          (t
+           (package-install
+            (cadr (assq package package-archive-contents)))))))

 (defun package--updateable-packages ()
   ;; Initialize the package system to get the list of package
@@ -2261,10 +2266,14 @@ package--updateable-packages
                  (assq (car elt) package-archive-contents)))
             (and available
                  (version-list-<
-                  (package-desc-version (cadr elt))
+                  (if (vectorp (cdr elt)) (aref (cdr elt) 0)
+                    (package-desc-version (cadr elt)))
                   (package-desc-version (cadr available)))))
-          (package-vc-p (cadr (assq (car elt) package-alist)))))
-    package-alist)))
+          (and (consp (cdr elt))
+               (package-desc-p (cadr elt))
+               (package-vc-p (cadr elt)))))
+    (seq-union package-alist package--builtins
+               (lambda (a b) (eq (car a) (car b)))))))

 ;;;###autoload
 (defun package-update-all (&optional query)

The only thing that's slightly inelegant/hard-to-follow is that
the format of package-alist is different than package--builtins.
Lots of consp, cdr-taking, vectorp and so on.  Besides that, it's
a question of taking the union of the two sets and operating on that.

This also relies on seq-union's undocumented behavior of keeping
the first of any duplicates.  Feel free to rewrite.

João